//----------------------------------------------------------------------------
//
//  TSDuck - The MPEG Transport Stream Toolkit
//
//  DES block cipher
//
//  Implementation based on LibTomCrypt (http://www.libtom.org/)
//  by Tom St Denis (tomstdenis@gmail.com)
//
//  Usage in TSDuck allowed based on LibTomCrypt licence:
//    << LibTomCrypt is public domain. The library is free for >>
//    << all purposes without any express guarantee it works.  >>
//
//----------------------------------------------------------------------------

#include "tsDES.h"
#include "tsRotate.h"


#define C64(x) TS_UCONST64(x)
#define BYTE(x,n) (((x) >> (8 * (n))) & 255)

namespace {

    static const uint32_t bytebit[8] = {
        0200, 0100, 040, 020, 010, 04, 02, 01
    };

    static const uint32_t bigbyte[24] = {
        0x800000UL,  0x400000UL,  0x200000UL,  0x100000UL,
        0x80000UL,   0x40000UL,   0x20000UL,   0x10000UL,
        0x8000UL,    0x4000UL,    0x2000UL,    0x1000UL,
        0x800UL,     0x400UL,     0x200UL,     0x100UL,
        0x80UL,      0x40UL,      0x20UL,      0x10UL,
        0x8UL,       0x4UL,       0x2UL,       0x1L
    };

    // Use the key schedule specific in the standard (ANSI X3.92-1981)

    static const uint8_t pc1[56] = {
        56, 48, 40, 32, 24, 16,  8,  0, 57, 49, 41, 33, 25, 17,
         9,  1, 58, 50, 42, 34, 26, 18, 10,  2, 59, 51, 43, 35,
        62, 54, 46, 38, 30, 22, 14,  6, 61, 53, 45, 37, 29, 21,
        13,  5, 60, 52, 44, 36, 28, 20, 12,  4, 27, 19, 11,  3
    };

    static const uint8_t totrot[16] = {
        1,   2,  4,  6,
        8,  10, 12, 14,
        15, 17, 19, 21,
        23, 25, 27, 28
    };

    static const uint8_t pc2[48] = {
        13, 16, 10, 23,  0,  4,      2, 27, 14,  5, 20,  9,
        22, 18, 11,  3, 25,  7,     15,  6, 26, 19, 12,  1,
        40, 51, 30, 36, 46, 54,     29, 39, 50, 44, 32, 47,
        43, 48, 38, 55, 33, 52,     45, 41, 49, 35, 28, 31
    };

    static const uint32_t SP1[64] = {
        0x01010400UL, 0x00000000UL, 0x00010000UL, 0x01010404UL,
        0x01010004UL, 0x00010404UL, 0x00000004UL, 0x00010000UL,
        0x00000400UL, 0x01010400UL, 0x01010404UL, 0x00000400UL,
        0x01000404UL, 0x01010004UL, 0x01000000UL, 0x00000004UL,
        0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00010400UL,
        0x00010400UL, 0x01010000UL, 0x01010000UL, 0x01000404UL,
        0x00010004UL, 0x01000004UL, 0x01000004UL, 0x00010004UL,
        0x00000000UL, 0x00000404UL, 0x00010404UL, 0x01000000UL,
        0x00010000UL, 0x01010404UL, 0x00000004UL, 0x01010000UL,
        0x01010400UL, 0x01000000UL, 0x01000000UL, 0x00000400UL,
        0x01010004UL, 0x00010000UL, 0x00010400UL, 0x01000004UL,
        0x00000400UL, 0x00000004UL, 0x01000404UL, 0x00010404UL,
        0x01010404UL, 0x00010004UL, 0x01010000UL, 0x01000404UL,
        0x01000004UL, 0x00000404UL, 0x00010404UL, 0x01010400UL,
        0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00000000UL,
        0x00010004UL, 0x00010400UL, 0x00000000UL, 0x01010004UL
    };

    static const uint32_t SP2[64] = {
        0x80108020UL, 0x80008000UL, 0x00008000UL, 0x00108020UL,
        0x00100000UL, 0x00000020UL, 0x80100020UL, 0x80008020UL,
        0x80000020UL, 0x80108020UL, 0x80108000UL, 0x80000000UL,
        0x80008000UL, 0x00100000UL, 0x00000020UL, 0x80100020UL,
        0x00108000UL, 0x00100020UL, 0x80008020UL, 0x00000000UL,
        0x80000000UL, 0x00008000UL, 0x00108020UL, 0x80100000UL,
        0x00100020UL, 0x80000020UL, 0x00000000UL, 0x00108000UL,
        0x00008020UL, 0x80108000UL, 0x80100000UL, 0x00008020UL,
        0x00000000UL, 0x00108020UL, 0x80100020UL, 0x00100000UL,
        0x80008020UL, 0x80100000UL, 0x80108000UL, 0x00008000UL,
        0x80100000UL, 0x80008000UL, 0x00000020UL, 0x80108020UL,
        0x00108020UL, 0x00000020UL, 0x00008000UL, 0x80000000UL,
        0x00008020UL, 0x80108000UL, 0x00100000UL, 0x80000020UL,
        0x00100020UL, 0x80008020UL, 0x80000020UL, 0x00100020UL,
        0x00108000UL, 0x00000000UL, 0x80008000UL, 0x00008020UL,
        0x80000000UL, 0x80100020UL, 0x80108020UL, 0x00108000UL
    };

    static const uint32_t SP3[64] = {
        0x00000208UL, 0x08020200UL, 0x00000000UL, 0x08020008UL,
        0x08000200UL, 0x00000000UL, 0x00020208UL, 0x08000200UL,
        0x00020008UL, 0x08000008UL, 0x08000008UL, 0x00020000UL,
        0x08020208UL, 0x00020008UL, 0x08020000UL, 0x00000208UL,
        0x08000000UL, 0x00000008UL, 0x08020200UL, 0x00000200UL,
        0x00020200UL, 0x08020000UL, 0x08020008UL, 0x00020208UL,
        0x08000208UL, 0x00020200UL, 0x00020000UL, 0x08000208UL,
        0x00000008UL, 0x08020208UL, 0x00000200UL, 0x08000000UL,
        0x08020200UL, 0x08000000UL, 0x00020008UL, 0x00000208UL,
        0x00020000UL, 0x08020200UL, 0x08000200UL, 0x00000000UL,
        0x00000200UL, 0x00020008UL, 0x08020208UL, 0x08000200UL,
        0x08000008UL, 0x00000200UL, 0x00000000UL, 0x08020008UL,
        0x08000208UL, 0x00020000UL, 0x08000000UL, 0x08020208UL,
        0x00000008UL, 0x00020208UL, 0x00020200UL, 0x08000008UL,
        0x08020000UL, 0x08000208UL, 0x00000208UL, 0x08020000UL,
        0x00020208UL, 0x00000008UL, 0x08020008UL, 0x00020200UL
    };

    static const uint32_t SP4[64] = {
        0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL,
        0x00802080UL, 0x00800081UL, 0x00800001UL, 0x00002001UL,
        0x00000000UL, 0x00802000UL, 0x00802000UL, 0x00802081UL,
        0x00000081UL, 0x00000000UL, 0x00800080UL, 0x00800001UL,
        0x00000001UL, 0x00002000UL, 0x00800000UL, 0x00802001UL,
        0x00000080UL, 0x00800000UL, 0x00002001UL, 0x00002080UL,
        0x00800081UL, 0x00000001UL, 0x00002080UL, 0x00800080UL,
        0x00002000UL, 0x00802080UL, 0x00802081UL, 0x00000081UL,
        0x00800080UL, 0x00800001UL, 0x00802000UL, 0x00802081UL,
        0x00000081UL, 0x00000000UL, 0x00000000UL, 0x00802000UL,
        0x00002080UL, 0x00800080UL, 0x00800081UL, 0x00000001UL,
        0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL,
        0x00802081UL, 0x00000081UL, 0x00000001UL, 0x00002000UL,
        0x00800001UL, 0x00002001UL, 0x00802080UL, 0x00800081UL,
        0x00002001UL, 0x00002080UL, 0x00800000UL, 0x00802001UL,
        0x00000080UL, 0x00800000UL, 0x00002000UL, 0x00802080UL
    };

    static const uint32_t SP5[64] = {
        0x00000100UL, 0x02080100UL, 0x02080000UL, 0x42000100UL,
        0x00080000UL, 0x00000100UL, 0x40000000UL, 0x02080000UL,
        0x40080100UL, 0x00080000UL, 0x02000100UL, 0x40080100UL,
        0x42000100UL, 0x42080000UL, 0x00080100UL, 0x40000000UL,
        0x02000000UL, 0x40080000UL, 0x40080000UL, 0x00000000UL,
        0x40000100UL, 0x42080100UL, 0x42080100UL, 0x02000100UL,
        0x42080000UL, 0x40000100UL, 0x00000000UL, 0x42000000UL,
        0x02080100UL, 0x02000000UL, 0x42000000UL, 0x00080100UL,
        0x00080000UL, 0x42000100UL, 0x00000100UL, 0x02000000UL,
        0x40000000UL, 0x02080000UL, 0x42000100UL, 0x40080100UL,
        0x02000100UL, 0x40000000UL, 0x42080000UL, 0x02080100UL,
        0x40080100UL, 0x00000100UL, 0x02000000UL, 0x42080000UL,
        0x42080100UL, 0x00080100UL, 0x42000000UL, 0x42080100UL,
        0x02080000UL, 0x00000000UL, 0x40080000UL, 0x42000000UL,
        0x00080100UL, 0x02000100UL, 0x40000100UL, 0x00080000UL,
        0x00000000UL, 0x40080000UL, 0x02080100UL, 0x40000100UL
    };

    static const uint32_t SP6[64] = {
        0x20000010UL, 0x20400000UL, 0x00004000UL, 0x20404010UL,
        0x20400000UL, 0x00000010UL, 0x20404010UL, 0x00400000UL,
        0x20004000UL, 0x00404010UL, 0x00400000UL, 0x20000010UL,
        0x00400010UL, 0x20004000UL, 0x20000000UL, 0x00004010UL,
        0x00000000UL, 0x00400010UL, 0x20004010UL, 0x00004000UL,
        0x00404000UL, 0x20004010UL, 0x00000010UL, 0x20400010UL,
        0x20400010UL, 0x00000000UL, 0x00404010UL, 0x20404000UL,
        0x00004010UL, 0x00404000UL, 0x20404000UL, 0x20000000UL,
        0x20004000UL, 0x00000010UL, 0x20400010UL, 0x00404000UL,
        0x20404010UL, 0x00400000UL, 0x00004010UL, 0x20000010UL,
        0x00400000UL, 0x20004000UL, 0x20000000UL, 0x00004010UL,
        0x20000010UL, 0x20404010UL, 0x00404000UL, 0x20400000UL,
        0x00404010UL, 0x20404000UL, 0x00000000UL, 0x20400010UL,
        0x00000010UL, 0x00004000UL, 0x20400000UL, 0x00404010UL,
        0x00004000UL, 0x00400010UL, 0x20004010UL, 0x00000000UL,
        0x20404000UL, 0x20000000UL, 0x00400010UL, 0x20004010UL
    };

    static const uint32_t SP7[64] = {
        0x00200000UL, 0x04200002UL, 0x04000802UL, 0x00000000UL,
        0x00000800UL, 0x04000802UL, 0x00200802UL, 0x04200800UL,
        0x04200802UL, 0x00200000UL, 0x00000000UL, 0x04000002UL,
        0x00000002UL, 0x04000000UL, 0x04200002UL, 0x00000802UL,
        0x04000800UL, 0x00200802UL, 0x00200002UL, 0x04000800UL,
        0x04000002UL, 0x04200000UL, 0x04200800UL, 0x00200002UL,
        0x04200000UL, 0x00000800UL, 0x00000802UL, 0x04200802UL,
        0x00200800UL, 0x00000002UL, 0x04000000UL, 0x00200800UL,
        0x04000000UL, 0x00200800UL, 0x00200000UL, 0x04000802UL,
        0x04000802UL, 0x04200002UL, 0x04200002UL, 0x00000002UL,
        0x00200002UL, 0x04000000UL, 0x04000800UL, 0x00200000UL,
        0x04200800UL, 0x00000802UL, 0x00200802UL, 0x04200800UL,
        0x00000802UL, 0x04000002UL, 0x04200802UL, 0x04200000UL,
        0x00200800UL, 0x00000000UL, 0x00000002UL, 0x04200802UL,
        0x00000000UL, 0x00200802UL, 0x04200000UL, 0x00000800UL,
        0x04000002UL, 0x04000800UL, 0x00000800UL, 0x00200002UL
    };

    static const uint32_t SP8[64] = {
            0x10001040UL, 0x00001000UL, 0x00040000UL, 0x10041040UL,
            0x10000000UL, 0x10001040UL, 0x00000040UL, 0x10000000UL,
            0x00040040UL, 0x10040000UL, 0x10041040UL, 0x00041000UL,
            0x10041000UL, 0x00041040UL, 0x00001000UL, 0x00000040UL,
            0x10040000UL, 0x10000040UL, 0x10001000UL, 0x00001040UL,
            0x00041000UL, 0x00040040UL, 0x10040040UL, 0x10041000UL,
            0x00001040UL, 0x00000000UL, 0x00000000UL, 0x10040040UL,
            0x10000040UL, 0x10001000UL, 0x00041040UL, 0x00040000UL,
            0x00041040UL, 0x00040000UL, 0x10041000UL, 0x00001000UL,
            0x00000040UL, 0x10040040UL, 0x00001000UL, 0x00041040UL,
            0x10001000UL, 0x00000040UL, 0x10000040UL, 0x10040000UL,
            0x10040040UL, 0x10000000UL, 0x00040000UL, 0x10001040UL,
            0x00000000UL, 0x10041040UL, 0x00040040UL, 0x10000040UL,
            0x10040000UL, 0x10001000UL, 0x10001040UL, 0x00000000UL,
            0x10041040UL, 0x00041000UL, 0x00041000UL, 0x00001040UL,
            0x00001040UL, 0x00040040UL, 0x10000000UL, 0x10041000UL
        };

    static const uint64_t des_ip[8][256] = {
        { C64(0x0000000000000000), C64(0x0000001000000000), C64(0x0000000000000010), C64(0x0000001000000010),
          C64(0x0000100000000000), C64(0x0000101000000000), C64(0x0000100000000010), C64(0x0000101000000010),
          C64(0x0000000000001000), C64(0x0000001000001000), C64(0x0000000000001010), C64(0x0000001000001010),
          C64(0x0000100000001000), C64(0x0000101000001000), C64(0x0000100000001010), C64(0x0000101000001010),
          C64(0x0010000000000000), C64(0x0010001000000000), C64(0x0010000000000010), C64(0x0010001000000010),
          C64(0x0010100000000000), C64(0x0010101000000000), C64(0x0010100000000010), C64(0x0010101000000010),
          C64(0x0010000000001000), C64(0x0010001000001000), C64(0x0010000000001010), C64(0x0010001000001010),
          C64(0x0010100000001000), C64(0x0010101000001000), C64(0x0010100000001010), C64(0x0010101000001010),
          C64(0x0000000000100000), C64(0x0000001000100000), C64(0x0000000000100010), C64(0x0000001000100010),
          C64(0x0000100000100000), C64(0x0000101000100000), C64(0x0000100000100010), C64(0x0000101000100010),
          C64(0x0000000000101000), C64(0x0000001000101000), C64(0x0000000000101010), C64(0x0000001000101010),
          C64(0x0000100000101000), C64(0x0000101000101000), C64(0x0000100000101010), C64(0x0000101000101010),
          C64(0x0010000000100000), C64(0x0010001000100000), C64(0x0010000000100010), C64(0x0010001000100010),
          C64(0x0010100000100000), C64(0x0010101000100000), C64(0x0010100000100010), C64(0x0010101000100010),
          C64(0x0010000000101000), C64(0x0010001000101000), C64(0x0010000000101010), C64(0x0010001000101010),
          C64(0x0010100000101000), C64(0x0010101000101000), C64(0x0010100000101010), C64(0x0010101000101010),
          C64(0x1000000000000000), C64(0x1000001000000000), C64(0x1000000000000010), C64(0x1000001000000010),
          C64(0x1000100000000000), C64(0x1000101000000000), C64(0x1000100000000010), C64(0x1000101000000010),
          C64(0x1000000000001000), C64(0x1000001000001000), C64(0x1000000000001010), C64(0x1000001000001010),
          C64(0x1000100000001000), C64(0x1000101000001000), C64(0x1000100000001010), C64(0x1000101000001010),
          C64(0x1010000000000000), C64(0x1010001000000000), C64(0x1010000000000010), C64(0x1010001000000010),
          C64(0x1010100000000000), C64(0x1010101000000000), C64(0x1010100000000010), C64(0x1010101000000010),
          C64(0x1010000000001000), C64(0x1010001000001000), C64(0x1010000000001010), C64(0x1010001000001010),
          C64(0x1010100000001000), C64(0x1010101000001000), C64(0x1010100000001010), C64(0x1010101000001010),
          C64(0x1000000000100000), C64(0x1000001000100000), C64(0x1000000000100010), C64(0x1000001000100010),
          C64(0x1000100000100000), C64(0x1000101000100000), C64(0x1000100000100010), C64(0x1000101000100010),
          C64(0x1000000000101000), C64(0x1000001000101000), C64(0x1000000000101010), C64(0x1000001000101010),
          C64(0x1000100000101000), C64(0x1000101000101000), C64(0x1000100000101010), C64(0x1000101000101010),
          C64(0x1010000000100000), C64(0x1010001000100000), C64(0x1010000000100010), C64(0x1010001000100010),
          C64(0x1010100000100000), C64(0x1010101000100000), C64(0x1010100000100010), C64(0x1010101000100010),
          C64(0x1010000000101000), C64(0x1010001000101000), C64(0x1010000000101010), C64(0x1010001000101010),
          C64(0x1010100000101000), C64(0x1010101000101000), C64(0x1010100000101010), C64(0x1010101000101010),
          C64(0x0000000010000000), C64(0x0000001010000000), C64(0x0000000010000010), C64(0x0000001010000010),
          C64(0x0000100010000000), C64(0x0000101010000000), C64(0x0000100010000010), C64(0x0000101010000010),
          C64(0x0000000010001000), C64(0x0000001010001000), C64(0x0000000010001010), C64(0x0000001010001010),
          C64(0x0000100010001000), C64(0x0000101010001000), C64(0x0000100010001010), C64(0x0000101010001010),
          C64(0x0010000010000000), C64(0x0010001010000000), C64(0x0010000010000010), C64(0x0010001010000010),
          C64(0x0010100010000000), C64(0x0010101010000000), C64(0x0010100010000010), C64(0x0010101010000010),
          C64(0x0010000010001000), C64(0x0010001010001000), C64(0x0010000010001010), C64(0x0010001010001010),
          C64(0x0010100010001000), C64(0x0010101010001000), C64(0x0010100010001010), C64(0x0010101010001010),
          C64(0x0000000010100000), C64(0x0000001010100000), C64(0x0000000010100010), C64(0x0000001010100010),
          C64(0x0000100010100000), C64(0x0000101010100000), C64(0x0000100010100010), C64(0x0000101010100010),
          C64(0x0000000010101000), C64(0x0000001010101000), C64(0x0000000010101010), C64(0x0000001010101010),
          C64(0x0000100010101000), C64(0x0000101010101000), C64(0x0000100010101010), C64(0x0000101010101010),
          C64(0x0010000010100000), C64(0x0010001010100000), C64(0x0010000010100010), C64(0x0010001010100010),
          C64(0x0010100010100000), C64(0x0010101010100000), C64(0x0010100010100010), C64(0x0010101010100010),
          C64(0x0010000010101000), C64(0x0010001010101000), C64(0x0010000010101010), C64(0x0010001010101010),
          C64(0x0010100010101000), C64(0x0010101010101000), C64(0x0010100010101010), C64(0x0010101010101010),
          C64(0x1000000010000000), C64(0x1000001010000000), C64(0x1000000010000010), C64(0x1000001010000010),
          C64(0x1000100010000000), C64(0x1000101010000000), C64(0x1000100010000010), C64(0x1000101010000010),
          C64(0x1000000010001000), C64(0x1000001010001000), C64(0x1000000010001010), C64(0x1000001010001010),
          C64(0x1000100010001000), C64(0x1000101010001000), C64(0x1000100010001010), C64(0x1000101010001010),
          C64(0x1010000010000000), C64(0x1010001010000000), C64(0x1010000010000010), C64(0x1010001010000010),
          C64(0x1010100010000000), C64(0x1010101010000000), C64(0x1010100010000010), C64(0x1010101010000010),
          C64(0x1010000010001000), C64(0x1010001010001000), C64(0x1010000010001010), C64(0x1010001010001010),
          C64(0x1010100010001000), C64(0x1010101010001000), C64(0x1010100010001010), C64(0x1010101010001010),
          C64(0x1000000010100000), C64(0x1000001010100000), C64(0x1000000010100010), C64(0x1000001010100010),
          C64(0x1000100010100000), C64(0x1000101010100000), C64(0x1000100010100010), C64(0x1000101010100010),
          C64(0x1000000010101000), C64(0x1000001010101000), C64(0x1000000010101010), C64(0x1000001010101010),
          C64(0x1000100010101000), C64(0x1000101010101000), C64(0x1000100010101010), C64(0x1000101010101010),
          C64(0x1010000010100000), C64(0x1010001010100000), C64(0x1010000010100010), C64(0x1010001010100010),
          C64(0x1010100010100000), C64(0x1010101010100000), C64(0x1010100010100010), C64(0x1010101010100010),
          C64(0x1010000010101000), C64(0x1010001010101000), C64(0x1010000010101010), C64(0x1010001010101010),
          C64(0x1010100010101000), C64(0x1010101010101000), C64(0x1010100010101010), C64(0x1010101010101010)
        },
        { C64(0x0000000000000000), C64(0x0000000800000000), C64(0x0000000000000008), C64(0x0000000800000008),
          C64(0x0000080000000000), C64(0x0000080800000000), C64(0x0000080000000008), C64(0x0000080800000008),
          C64(0x0000000000000800), C64(0x0000000800000800), C64(0x0000000000000808), C64(0x0000000800000808),
          C64(0x0000080000000800), C64(0x0000080800000800), C64(0x0000080000000808), C64(0x0000080800000808),
          C64(0x0008000000000000), C64(0x0008000800000000), C64(0x0008000000000008), C64(0x0008000800000008),
          C64(0x0008080000000000), C64(0x0008080800000000), C64(0x0008080000000008), C64(0x0008080800000008),
          C64(0x0008000000000800), C64(0x0008000800000800), C64(0x0008000000000808), C64(0x0008000800000808),
          C64(0x0008080000000800), C64(0x0008080800000800), C64(0x0008080000000808), C64(0x0008080800000808),
          C64(0x0000000000080000), C64(0x0000000800080000), C64(0x0000000000080008), C64(0x0000000800080008),
          C64(0x0000080000080000), C64(0x0000080800080000), C64(0x0000080000080008), C64(0x0000080800080008),
          C64(0x0000000000080800), C64(0x0000000800080800), C64(0x0000000000080808), C64(0x0000000800080808),
          C64(0x0000080000080800), C64(0x0000080800080800), C64(0x0000080000080808), C64(0x0000080800080808),
          C64(0x0008000000080000), C64(0x0008000800080000), C64(0x0008000000080008), C64(0x0008000800080008),
          C64(0x0008080000080000), C64(0x0008080800080000), C64(0x0008080000080008), C64(0x0008080800080008),
          C64(0x0008000000080800), C64(0x0008000800080800), C64(0x0008000000080808), C64(0x0008000800080808),
          C64(0x0008080000080800), C64(0x0008080800080800), C64(0x0008080000080808), C64(0x0008080800080808),
          C64(0x0800000000000000), C64(0x0800000800000000), C64(0x0800000000000008), C64(0x0800000800000008),
          C64(0x0800080000000000), C64(0x0800080800000000), C64(0x0800080000000008), C64(0x0800080800000008),
          C64(0x0800000000000800), C64(0x0800000800000800), C64(0x0800000000000808), C64(0x0800000800000808),
          C64(0x0800080000000800), C64(0x0800080800000800), C64(0x0800080000000808), C64(0x0800080800000808),
          C64(0x0808000000000000), C64(0x0808000800000000), C64(0x0808000000000008), C64(0x0808000800000008),
          C64(0x0808080000000000), C64(0x0808080800000000), C64(0x0808080000000008), C64(0x0808080800000008),
          C64(0x0808000000000800), C64(0x0808000800000800), C64(0x0808000000000808), C64(0x0808000800000808),
          C64(0x0808080000000800), C64(0x0808080800000800), C64(0x0808080000000808), C64(0x0808080800000808),
          C64(0x0800000000080000), C64(0x0800000800080000), C64(0x0800000000080008), C64(0x0800000800080008),
          C64(0x0800080000080000), C64(0x0800080800080000), C64(0x0800080000080008), C64(0x0800080800080008),
          C64(0x0800000000080800), C64(0x0800000800080800), C64(0x0800000000080808), C64(0x0800000800080808),
          C64(0x0800080000080800), C64(0x0800080800080800), C64(0x0800080000080808), C64(0x0800080800080808),
          C64(0x0808000000080000), C64(0x0808000800080000), C64(0x0808000000080008), C64(0x0808000800080008),
          C64(0x0808080000080000), C64(0x0808080800080000), C64(0x0808080000080008), C64(0x0808080800080008),
          C64(0x0808000000080800), C64(0x0808000800080800), C64(0x0808000000080808), C64(0x0808000800080808),
          C64(0x0808080000080800), C64(0x0808080800080800), C64(0x0808080000080808), C64(0x0808080800080808),
          C64(0x0000000008000000), C64(0x0000000808000000), C64(0x0000000008000008), C64(0x0000000808000008),
          C64(0x0000080008000000), C64(0x0000080808000000), C64(0x0000080008000008), C64(0x0000080808000008),
          C64(0x0000000008000800), C64(0x0000000808000800), C64(0x0000000008000808), C64(0x0000000808000808),
          C64(0x0000080008000800), C64(0x0000080808000800), C64(0x0000080008000808), C64(0x0000080808000808),
          C64(0x0008000008000000), C64(0x0008000808000000), C64(0x0008000008000008), C64(0x0008000808000008),
          C64(0x0008080008000000), C64(0x0008080808000000), C64(0x0008080008000008), C64(0x0008080808000008),
          C64(0x0008000008000800), C64(0x0008000808000800), C64(0x0008000008000808), C64(0x0008000808000808),
          C64(0x0008080008000800), C64(0x0008080808000800), C64(0x0008080008000808), C64(0x0008080808000808),
          C64(0x0000000008080000), C64(0x0000000808080000), C64(0x0000000008080008), C64(0x0000000808080008),
          C64(0x0000080008080000), C64(0x0000080808080000), C64(0x0000080008080008), C64(0x0000080808080008),
          C64(0x0000000008080800), C64(0x0000000808080800), C64(0x0000000008080808), C64(0x0000000808080808),
          C64(0x0000080008080800), C64(0x0000080808080800), C64(0x0000080008080808), C64(0x0000080808080808),
          C64(0x0008000008080000), C64(0x0008000808080000), C64(0x0008000008080008), C64(0x0008000808080008),
          C64(0x0008080008080000), C64(0x0008080808080000), C64(0x0008080008080008), C64(0x0008080808080008),
          C64(0x0008000008080800), C64(0x0008000808080800), C64(0x0008000008080808), C64(0x0008000808080808),
          C64(0x0008080008080800), C64(0x0008080808080800), C64(0x0008080008080808), C64(0x0008080808080808),
          C64(0x0800000008000000), C64(0x0800000808000000), C64(0x0800000008000008), C64(0x0800000808000008),
          C64(0x0800080008000000), C64(0x0800080808000000), C64(0x0800080008000008), C64(0x0800080808000008),
          C64(0x0800000008000800), C64(0x0800000808000800), C64(0x0800000008000808), C64(0x0800000808000808),
          C64(0x0800080008000800), C64(0x0800080808000800), C64(0x0800080008000808), C64(0x0800080808000808),
          C64(0x0808000008000000), C64(0x0808000808000000), C64(0x0808000008000008), C64(0x0808000808000008),
          C64(0x0808080008000000), C64(0x0808080808000000), C64(0x0808080008000008), C64(0x0808080808000008),
          C64(0x0808000008000800), C64(0x0808000808000800), C64(0x0808000008000808), C64(0x0808000808000808),
          C64(0x0808080008000800), C64(0x0808080808000800), C64(0x0808080008000808), C64(0x0808080808000808),
          C64(0x0800000008080000), C64(0x0800000808080000), C64(0x0800000008080008), C64(0x0800000808080008),
          C64(0x0800080008080000), C64(0x0800080808080000), C64(0x0800080008080008), C64(0x0800080808080008),
          C64(0x0800000008080800), C64(0x0800000808080800), C64(0x0800000008080808), C64(0x0800000808080808),
          C64(0x0800080008080800), C64(0x0800080808080800), C64(0x0800080008080808), C64(0x0800080808080808),
          C64(0x0808000008080000), C64(0x0808000808080000), C64(0x0808000008080008), C64(0x0808000808080008),
          C64(0x0808080008080000), C64(0x0808080808080000), C64(0x0808080008080008), C64(0x0808080808080008),
          C64(0x0808000008080800), C64(0x0808000808080800), C64(0x0808000008080808), C64(0x0808000808080808),
          C64(0x0808080008080800), C64(0x0808080808080800), C64(0x0808080008080808), C64(0x0808080808080808)
        },
        { C64(0x0000000000000000), C64(0x0000000400000000), C64(0x0000000000000004), C64(0x0000000400000004),
          C64(0x0000040000000000), C64(0x0000040400000000), C64(0x0000040000000004), C64(0x0000040400000004),
          C64(0x0000000000000400), C64(0x0000000400000400), C64(0x0000000000000404), C64(0x0000000400000404),
          C64(0x0000040000000400), C64(0x0000040400000400), C64(0x0000040000000404), C64(0x0000040400000404),
          C64(0x0004000000000000), C64(0x0004000400000000), C64(0x0004000000000004), C64(0x0004000400000004),
          C64(0x0004040000000000), C64(0x0004040400000000), C64(0x0004040000000004), C64(0x0004040400000004),
          C64(0x0004000000000400), C64(0x0004000400000400), C64(0x0004000000000404), C64(0x0004000400000404),
          C64(0x0004040000000400), C64(0x0004040400000400), C64(0x0004040000000404), C64(0x0004040400000404),
          C64(0x0000000000040000), C64(0x0000000400040000), C64(0x0000000000040004), C64(0x0000000400040004),
          C64(0x0000040000040000), C64(0x0000040400040000), C64(0x0000040000040004), C64(0x0000040400040004),
          C64(0x0000000000040400), C64(0x0000000400040400), C64(0x0000000000040404), C64(0x0000000400040404),
          C64(0x0000040000040400), C64(0x0000040400040400), C64(0x0000040000040404), C64(0x0000040400040404),
          C64(0x0004000000040000), C64(0x0004000400040000), C64(0x0004000000040004), C64(0x0004000400040004),
          C64(0x0004040000040000), C64(0x0004040400040000), C64(0x0004040000040004), C64(0x0004040400040004),
          C64(0x0004000000040400), C64(0x0004000400040400), C64(0x0004000000040404), C64(0x0004000400040404),
          C64(0x0004040000040400), C64(0x0004040400040400), C64(0x0004040000040404), C64(0x0004040400040404),
          C64(0x0400000000000000), C64(0x0400000400000000), C64(0x0400000000000004), C64(0x0400000400000004),
          C64(0x0400040000000000), C64(0x0400040400000000), C64(0x0400040000000004), C64(0x0400040400000004),
          C64(0x0400000000000400), C64(0x0400000400000400), C64(0x0400000000000404), C64(0x0400000400000404),
          C64(0x0400040000000400), C64(0x0400040400000400), C64(0x0400040000000404), C64(0x0400040400000404),
          C64(0x0404000000000000), C64(0x0404000400000000), C64(0x0404000000000004), C64(0x0404000400000004),
          C64(0x0404040000000000), C64(0x0404040400000000), C64(0x0404040000000004), C64(0x0404040400000004),
          C64(0x0404000000000400), C64(0x0404000400000400), C64(0x0404000000000404), C64(0x0404000400000404),
          C64(0x0404040000000400), C64(0x0404040400000400), C64(0x0404040000000404), C64(0x0404040400000404),
          C64(0x0400000000040000), C64(0x0400000400040000), C64(0x0400000000040004), C64(0x0400000400040004),
          C64(0x0400040000040000), C64(0x0400040400040000), C64(0x0400040000040004), C64(0x0400040400040004),
          C64(0x0400000000040400), C64(0x0400000400040400), C64(0x0400000000040404), C64(0x0400000400040404),
          C64(0x0400040000040400), C64(0x0400040400040400), C64(0x0400040000040404), C64(0x0400040400040404),
          C64(0x0404000000040000), C64(0x0404000400040000), C64(0x0404000000040004), C64(0x0404000400040004),
          C64(0x0404040000040000), C64(0x0404040400040000), C64(0x0404040000040004), C64(0x0404040400040004),
          C64(0x0404000000040400), C64(0x0404000400040400), C64(0x0404000000040404), C64(0x0404000400040404),
          C64(0x0404040000040400), C64(0x0404040400040400), C64(0x0404040000040404), C64(0x0404040400040404),
          C64(0x0000000004000000), C64(0x0000000404000000), C64(0x0000000004000004), C64(0x0000000404000004),
          C64(0x0000040004000000), C64(0x0000040404000000), C64(0x0000040004000004), C64(0x0000040404000004),
          C64(0x0000000004000400), C64(0x0000000404000400), C64(0x0000000004000404), C64(0x0000000404000404),
          C64(0x0000040004000400), C64(0x0000040404000400), C64(0x0000040004000404), C64(0x0000040404000404),
          C64(0x0004000004000000), C64(0x0004000404000000), C64(0x0004000004000004), C64(0x0004000404000004),
          C64(0x0004040004000000), C64(0x0004040404000000), C64(0x0004040004000004), C64(0x0004040404000004),
          C64(0x0004000004000400), C64(0x0004000404000400), C64(0x0004000004000404), C64(0x0004000404000404),
          C64(0x0004040004000400), C64(0x0004040404000400), C64(0x0004040004000404), C64(0x0004040404000404),
          C64(0x0000000004040000), C64(0x0000000404040000), C64(0x0000000004040004), C64(0x0000000404040004),
          C64(0x0000040004040000), C64(0x0000040404040000), C64(0x0000040004040004), C64(0x0000040404040004),
          C64(0x0000000004040400), C64(0x0000000404040400), C64(0x0000000004040404), C64(0x0000000404040404),
          C64(0x0000040004040400), C64(0x0000040404040400), C64(0x0000040004040404), C64(0x0000040404040404),
          C64(0x0004000004040000), C64(0x0004000404040000), C64(0x0004000004040004), C64(0x0004000404040004),
          C64(0x0004040004040000), C64(0x0004040404040000), C64(0x0004040004040004), C64(0x0004040404040004),
          C64(0x0004000004040400), C64(0x0004000404040400), C64(0x0004000004040404), C64(0x0004000404040404),
          C64(0x0004040004040400), C64(0x0004040404040400), C64(0x0004040004040404), C64(0x0004040404040404),
          C64(0x0400000004000000), C64(0x0400000404000000), C64(0x0400000004000004), C64(0x0400000404000004),
          C64(0x0400040004000000), C64(0x0400040404000000), C64(0x0400040004000004), C64(0x0400040404000004),
          C64(0x0400000004000400), C64(0x0400000404000400), C64(0x0400000004000404), C64(0x0400000404000404),
          C64(0x0400040004000400), C64(0x0400040404000400), C64(0x0400040004000404), C64(0x0400040404000404),
          C64(0x0404000004000000), C64(0x0404000404000000), C64(0x0404000004000004), C64(0x0404000404000004),
          C64(0x0404040004000000), C64(0x0404040404000000), C64(0x0404040004000004), C64(0x0404040404000004),
          C64(0x0404000004000400), C64(0x0404000404000400), C64(0x0404000004000404), C64(0x0404000404000404),
          C64(0x0404040004000400), C64(0x0404040404000400), C64(0x0404040004000404), C64(0x0404040404000404),
          C64(0x0400000004040000), C64(0x0400000404040000), C64(0x0400000004040004), C64(0x0400000404040004),
          C64(0x0400040004040000), C64(0x0400040404040000), C64(0x0400040004040004), C64(0x0400040404040004),
          C64(0x0400000004040400), C64(0x0400000404040400), C64(0x0400000004040404), C64(0x0400000404040404),
          C64(0x0400040004040400), C64(0x0400040404040400), C64(0x0400040004040404), C64(0x0400040404040404),
          C64(0x0404000004040000), C64(0x0404000404040000), C64(0x0404000004040004), C64(0x0404000404040004),
          C64(0x0404040004040000), C64(0x0404040404040000), C64(0x0404040004040004), C64(0x0404040404040004),
          C64(0x0404000004040400), C64(0x0404000404040400), C64(0x0404000004040404), C64(0x0404000404040404),
          C64(0x0404040004040400), C64(0x0404040404040400), C64(0x0404040004040404), C64(0x0404040404040404)
        },
        { C64(0x0000000000000000), C64(0x0000000200000000), C64(0x0000000000000002), C64(0x0000000200000002),
          C64(0x0000020000000000), C64(0x0000020200000000), C64(0x0000020000000002), C64(0x0000020200000002),
          C64(0x0000000000000200), C64(0x0000000200000200), C64(0x0000000000000202), C64(0x0000000200000202),
          C64(0x0000020000000200), C64(0x0000020200000200), C64(0x0000020000000202), C64(0x0000020200000202),
          C64(0x0002000000000000), C64(0x0002000200000000), C64(0x0002000000000002), C64(0x0002000200000002),
          C64(0x0002020000000000), C64(0x0002020200000000), C64(0x0002020000000002), C64(0x0002020200000002),
          C64(0x0002000000000200), C64(0x0002000200000200), C64(0x0002000000000202), C64(0x0002000200000202),
          C64(0x0002020000000200), C64(0x0002020200000200), C64(0x0002020000000202), C64(0x0002020200000202),
          C64(0x0000000000020000), C64(0x0000000200020000), C64(0x0000000000020002), C64(0x0000000200020002),
          C64(0x0000020000020000), C64(0x0000020200020000), C64(0x0000020000020002), C64(0x0000020200020002),
          C64(0x0000000000020200), C64(0x0000000200020200), C64(0x0000000000020202), C64(0x0000000200020202),
          C64(0x0000020000020200), C64(0x0000020200020200), C64(0x0000020000020202), C64(0x0000020200020202),
          C64(0x0002000000020000), C64(0x0002000200020000), C64(0x0002000000020002), C64(0x0002000200020002),
          C64(0x0002020000020000), C64(0x0002020200020000), C64(0x0002020000020002), C64(0x0002020200020002),
          C64(0x0002000000020200), C64(0x0002000200020200), C64(0x0002000000020202), C64(0x0002000200020202),
          C64(0x0002020000020200), C64(0x0002020200020200), C64(0x0002020000020202), C64(0x0002020200020202),
          C64(0x0200000000000000), C64(0x0200000200000000), C64(0x0200000000000002), C64(0x0200000200000002),
          C64(0x0200020000000000), C64(0x0200020200000000), C64(0x0200020000000002), C64(0x0200020200000002),
          C64(0x0200000000000200), C64(0x0200000200000200), C64(0x0200000000000202), C64(0x0200000200000202),
          C64(0x0200020000000200), C64(0x0200020200000200), C64(0x0200020000000202), C64(0x0200020200000202),
          C64(0x0202000000000000), C64(0x0202000200000000), C64(0x0202000000000002), C64(0x0202000200000002),
          C64(0x0202020000000000), C64(0x0202020200000000), C64(0x0202020000000002), C64(0x0202020200000002),
          C64(0x0202000000000200), C64(0x0202000200000200), C64(0x0202000000000202), C64(0x0202000200000202),
          C64(0x0202020000000200), C64(0x0202020200000200), C64(0x0202020000000202), C64(0x0202020200000202),
          C64(0x0200000000020000), C64(0x0200000200020000), C64(0x0200000000020002), C64(0x0200000200020002),
          C64(0x0200020000020000), C64(0x0200020200020000), C64(0x0200020000020002), C64(0x0200020200020002),
          C64(0x0200000000020200), C64(0x0200000200020200), C64(0x0200000000020202), C64(0x0200000200020202),
          C64(0x0200020000020200), C64(0x0200020200020200), C64(0x0200020000020202), C64(0x0200020200020202),
          C64(0x0202000000020000), C64(0x0202000200020000), C64(0x0202000000020002), C64(0x0202000200020002),
          C64(0x0202020000020000), C64(0x0202020200020000), C64(0x0202020000020002), C64(0x0202020200020002),
          C64(0x0202000000020200), C64(0x0202000200020200), C64(0x0202000000020202), C64(0x0202000200020202),
          C64(0x0202020000020200), C64(0x0202020200020200), C64(0x0202020000020202), C64(0x0202020200020202),
          C64(0x0000000002000000), C64(0x0000000202000000), C64(0x0000000002000002), C64(0x0000000202000002),
          C64(0x0000020002000000), C64(0x0000020202000000), C64(0x0000020002000002), C64(0x0000020202000002),
          C64(0x0000000002000200), C64(0x0000000202000200), C64(0x0000000002000202), C64(0x0000000202000202),
          C64(0x0000020002000200), C64(0x0000020202000200), C64(0x0000020002000202), C64(0x0000020202000202),
          C64(0x0002000002000000), C64(0x0002000202000000), C64(0x0002000002000002), C64(0x0002000202000002),
          C64(0x0002020002000000), C64(0x0002020202000000), C64(0x0002020002000002), C64(0x0002020202000002),
          C64(0x0002000002000200), C64(0x0002000202000200), C64(0x0002000002000202), C64(0x0002000202000202),
          C64(0x0002020002000200), C64(0x0002020202000200), C64(0x0002020002000202), C64(0x0002020202000202),
          C64(0x0000000002020000), C64(0x0000000202020000), C64(0x0000000002020002), C64(0x0000000202020002),
          C64(0x0000020002020000), C64(0x0000020202020000), C64(0x0000020002020002), C64(0x0000020202020002),
          C64(0x0000000002020200), C64(0x0000000202020200), C64(0x0000000002020202), C64(0x0000000202020202),
          C64(0x0000020002020200), C64(0x0000020202020200), C64(0x0000020002020202), C64(0x0000020202020202),
          C64(0x0002000002020000), C64(0x0002000202020000), C64(0x0002000002020002), C64(0x0002000202020002),
          C64(0x0002020002020000), C64(0x0002020202020000), C64(0x0002020002020002), C64(0x0002020202020002),
          C64(0x0002000002020200), C64(0x0002000202020200), C64(0x0002000002020202), C64(0x0002000202020202),
          C64(0x0002020002020200), C64(0x0002020202020200), C64(0x0002020002020202), C64(0x0002020202020202),
          C64(0x0200000002000000), C64(0x0200000202000000), C64(0x0200000002000002), C64(0x0200000202000002),
          C64(0x0200020002000000), C64(0x0200020202000000), C64(0x0200020002000002), C64(0x0200020202000002),
          C64(0x0200000002000200), C64(0x0200000202000200), C64(0x0200000002000202), C64(0x0200000202000202),
          C64(0x0200020002000200), C64(0x0200020202000200), C64(0x0200020002000202), C64(0x0200020202000202),
          C64(0x0202000002000000), C64(0x0202000202000000), C64(0x0202000002000002), C64(0x0202000202000002),
          C64(0x0202020002000000), C64(0x0202020202000000), C64(0x0202020002000002), C64(0x0202020202000002),
          C64(0x0202000002000200), C64(0x0202000202000200), C64(0x0202000002000202), C64(0x0202000202000202),
          C64(0x0202020002000200), C64(0x0202020202000200), C64(0x0202020002000202), C64(0x0202020202000202),
          C64(0x0200000002020000), C64(0x0200000202020000), C64(0x0200000002020002), C64(0x0200000202020002),
          C64(0x0200020002020000), C64(0x0200020202020000), C64(0x0200020002020002), C64(0x0200020202020002),
          C64(0x0200000002020200), C64(0x0200000202020200), C64(0x0200000002020202), C64(0x0200000202020202),
          C64(0x0200020002020200), C64(0x0200020202020200), C64(0x0200020002020202), C64(0x0200020202020202),
          C64(0x0202000002020000), C64(0x0202000202020000), C64(0x0202000002020002), C64(0x0202000202020002),
          C64(0x0202020002020000), C64(0x0202020202020000), C64(0x0202020002020002), C64(0x0202020202020002),
          C64(0x0202000002020200), C64(0x0202000202020200), C64(0x0202000002020202), C64(0x0202000202020202),
          C64(0x0202020002020200), C64(0x0202020202020200), C64(0x0202020002020202), C64(0x0202020202020202)
        },
        { C64(0x0000000000000000), C64(0x0000010000000000), C64(0x0000000000000100), C64(0x0000010000000100),
          C64(0x0001000000000000), C64(0x0001010000000000), C64(0x0001000000000100), C64(0x0001010000000100),
          C64(0x0000000000010000), C64(0x0000010000010000), C64(0x0000000000010100), C64(0x0000010000010100),
          C64(0x0001000000010000), C64(0x0001010000010000), C64(0x0001000000010100), C64(0x0001010000010100),
          C64(0x0100000000000000), C64(0x0100010000000000), C64(0x0100000000000100), C64(0x0100010000000100),
          C64(0x0101000000000000), C64(0x0101010000000000), C64(0x0101000000000100), C64(0x0101010000000100),
          C64(0x0100000000010000), C64(0x0100010000010000), C64(0x0100000000010100), C64(0x0100010000010100),
          C64(0x0101000000010000), C64(0x0101010000010000), C64(0x0101000000010100), C64(0x0101010000010100),
          C64(0x0000000001000000), C64(0x0000010001000000), C64(0x0000000001000100), C64(0x0000010001000100),
          C64(0x0001000001000000), C64(0x0001010001000000), C64(0x0001000001000100), C64(0x0001010001000100),
          C64(0x0000000001010000), C64(0x0000010001010000), C64(0x0000000001010100), C64(0x0000010001010100),
          C64(0x0001000001010000), C64(0x0001010001010000), C64(0x0001000001010100), C64(0x0001010001010100),
          C64(0x0100000001000000), C64(0x0100010001000000), C64(0x0100000001000100), C64(0x0100010001000100),
          C64(0x0101000001000000), C64(0x0101010001000000), C64(0x0101000001000100), C64(0x0101010001000100),
          C64(0x0100000001010000), C64(0x0100010001010000), C64(0x0100000001010100), C64(0x0100010001010100),
          C64(0x0101000001010000), C64(0x0101010001010000), C64(0x0101000001010100), C64(0x0101010001010100),
          C64(0x0000000100000000), C64(0x0000010100000000), C64(0x0000000100000100), C64(0x0000010100000100),
          C64(0x0001000100000000), C64(0x0001010100000000), C64(0x0001000100000100), C64(0x0001010100000100),
          C64(0x0000000100010000), C64(0x0000010100010000), C64(0x0000000100010100), C64(0x0000010100010100),
          C64(0x0001000100010000), C64(0x0001010100010000), C64(0x0001000100010100), C64(0x0001010100010100),
          C64(0x0100000100000000), C64(0x0100010100000000), C64(0x0100000100000100), C64(0x0100010100000100),
          C64(0x0101000100000000), C64(0x0101010100000000), C64(0x0101000100000100), C64(0x0101010100000100),
          C64(0x0100000100010000), C64(0x0100010100010000), C64(0x0100000100010100), C64(0x0100010100010100),
          C64(0x0101000100010000), C64(0x0101010100010000), C64(0x0101000100010100), C64(0x0101010100010100),
          C64(0x0000000101000000), C64(0x0000010101000000), C64(0x0000000101000100), C64(0x0000010101000100),
          C64(0x0001000101000000), C64(0x0001010101000000), C64(0x0001000101000100), C64(0x0001010101000100),
          C64(0x0000000101010000), C64(0x0000010101010000), C64(0x0000000101010100), C64(0x0000010101010100),
          C64(0x0001000101010000), C64(0x0001010101010000), C64(0x0001000101010100), C64(0x0001010101010100),
          C64(0x0100000101000000), C64(0x0100010101000000), C64(0x0100000101000100), C64(0x0100010101000100),
          C64(0x0101000101000000), C64(0x0101010101000000), C64(0x0101000101000100), C64(0x0101010101000100),
          C64(0x0100000101010000), C64(0x0100010101010000), C64(0x0100000101010100), C64(0x0100010101010100),
          C64(0x0101000101010000), C64(0x0101010101010000), C64(0x0101000101010100), C64(0x0101010101010100),
          C64(0x0000000000000001), C64(0x0000010000000001), C64(0x0000000000000101), C64(0x0000010000000101),
          C64(0x0001000000000001), C64(0x0001010000000001), C64(0x0001000000000101), C64(0x0001010000000101),
          C64(0x0000000000010001), C64(0x0000010000010001), C64(0x0000000000010101), C64(0x0000010000010101),
          C64(0x0001000000010001), C64(0x0001010000010001), C64(0x0001000000010101), C64(0x0001010000010101),
          C64(0x0100000000000001), C64(0x0100010000000001), C64(0x0100000000000101), C64(0x0100010000000101),
          C64(0x0101000000000001), C64(0x0101010000000001), C64(0x0101000000000101), C64(0x0101010000000101),
          C64(0x0100000000010001), C64(0x0100010000010001), C64(0x0100000000010101), C64(0x0100010000010101),
          C64(0x0101000000010001), C64(0x0101010000010001), C64(0x0101000000010101), C64(0x0101010000010101),
          C64(0x0000000001000001), C64(0x0000010001000001), C64(0x0000000001000101), C64(0x0000010001000101),
          C64(0x0001000001000001), C64(0x0001010001000001), C64(0x0001000001000101), C64(0x0001010001000101),
          C64(0x0000000001010001), C64(0x0000010001010001), C64(0x0000000001010101), C64(0x0000010001010101),
          C64(0x0001000001010001), C64(0x0001010001010001), C64(0x0001000001010101), C64(0x0001010001010101),
          C64(0x0100000001000001), C64(0x0100010001000001), C64(0x0100000001000101), C64(0x0100010001000101),
          C64(0x0101000001000001), C64(0x0101010001000001), C64(0x0101000001000101), C64(0x0101010001000101),
          C64(0x0100000001010001), C64(0x0100010001010001), C64(0x0100000001010101), C64(0x0100010001010101),
          C64(0x0101000001010001), C64(0x0101010001010001), C64(0x0101000001010101), C64(0x0101010001010101),
          C64(0x0000000100000001), C64(0x0000010100000001), C64(0x0000000100000101), C64(0x0000010100000101),
          C64(0x0001000100000001), C64(0x0001010100000001), C64(0x0001000100000101), C64(0x0001010100000101),
          C64(0x0000000100010001), C64(0x0000010100010001), C64(0x0000000100010101), C64(0x0000010100010101),
          C64(0x0001000100010001), C64(0x0001010100010001), C64(0x0001000100010101), C64(0x0001010100010101),
          C64(0x0100000100000001), C64(0x0100010100000001), C64(0x0100000100000101), C64(0x0100010100000101),
          C64(0x0101000100000001), C64(0x0101010100000001), C64(0x0101000100000101), C64(0x0101010100000101),
          C64(0x0100000100010001), C64(0x0100010100010001), C64(0x0100000100010101), C64(0x0100010100010101),
          C64(0x0101000100010001), C64(0x0101010100010001), C64(0x0101000100010101), C64(0x0101010100010101),
          C64(0x0000000101000001), C64(0x0000010101000001), C64(0x0000000101000101), C64(0x0000010101000101),
          C64(0x0001000101000001), C64(0x0001010101000001), C64(0x0001000101000101), C64(0x0001010101000101),
          C64(0x0000000101010001), C64(0x0000010101010001), C64(0x0000000101010101), C64(0x0000010101010101),
          C64(0x0001000101010001), C64(0x0001010101010001), C64(0x0001000101010101), C64(0x0001010101010101),
          C64(0x0100000101000001), C64(0x0100010101000001), C64(0x0100000101000101), C64(0x0100010101000101),
          C64(0x0101000101000001), C64(0x0101010101000001), C64(0x0101000101000101), C64(0x0101010101000101),
          C64(0x0100000101010001), C64(0x0100010101010001), C64(0x0100000101010101), C64(0x0100010101010101),
          C64(0x0101000101010001), C64(0x0101010101010001), C64(0x0101000101010101), C64(0x0101010101010101)
        },
        { C64(0x0000000000000000), C64(0x0000008000000000), C64(0x0000000000000080), C64(0x0000008000000080),
          C64(0x0000800000000000), C64(0x0000808000000000), C64(0x0000800000000080), C64(0x0000808000000080),
          C64(0x0000000000008000), C64(0x0000008000008000), C64(0x0000000000008080), C64(0x0000008000008080),
          C64(0x0000800000008000), C64(0x0000808000008000), C64(0x0000800000008080), C64(0x0000808000008080),
          C64(0x0080000000000000), C64(0x0080008000000000), C64(0x0080000000000080), C64(0x0080008000000080),
          C64(0x0080800000000000), C64(0x0080808000000000), C64(0x0080800000000080), C64(0x0080808000000080),
          C64(0x0080000000008000), C64(0x0080008000008000), C64(0x0080000000008080), C64(0x0080008000008080),
          C64(0x0080800000008000), C64(0x0080808000008000), C64(0x0080800000008080), C64(0x0080808000008080),
          C64(0x0000000000800000), C64(0x0000008000800000), C64(0x0000000000800080), C64(0x0000008000800080),
          C64(0x0000800000800000), C64(0x0000808000800000), C64(0x0000800000800080), C64(0x0000808000800080),
          C64(0x0000000000808000), C64(0x0000008000808000), C64(0x0000000000808080), C64(0x0000008000808080),
          C64(0x0000800000808000), C64(0x0000808000808000), C64(0x0000800000808080), C64(0x0000808000808080),
          C64(0x0080000000800000), C64(0x0080008000800000), C64(0x0080000000800080), C64(0x0080008000800080),
          C64(0x0080800000800000), C64(0x0080808000800000), C64(0x0080800000800080), C64(0x0080808000800080),
          C64(0x0080000000808000), C64(0x0080008000808000), C64(0x0080000000808080), C64(0x0080008000808080),
          C64(0x0080800000808000), C64(0x0080808000808000), C64(0x0080800000808080), C64(0x0080808000808080),
          C64(0x8000000000000000), C64(0x8000008000000000), C64(0x8000000000000080), C64(0x8000008000000080),
          C64(0x8000800000000000), C64(0x8000808000000000), C64(0x8000800000000080), C64(0x8000808000000080),
          C64(0x8000000000008000), C64(0x8000008000008000), C64(0x8000000000008080), C64(0x8000008000008080),
          C64(0x8000800000008000), C64(0x8000808000008000), C64(0x8000800000008080), C64(0x8000808000008080),
          C64(0x8080000000000000), C64(0x8080008000000000), C64(0x8080000000000080), C64(0x8080008000000080),
          C64(0x8080800000000000), C64(0x8080808000000000), C64(0x8080800000000080), C64(0x8080808000000080),
          C64(0x8080000000008000), C64(0x8080008000008000), C64(0x8080000000008080), C64(0x8080008000008080),
          C64(0x8080800000008000), C64(0x8080808000008000), C64(0x8080800000008080), C64(0x8080808000008080),
          C64(0x8000000000800000), C64(0x8000008000800000), C64(0x8000000000800080), C64(0x8000008000800080),
          C64(0x8000800000800000), C64(0x8000808000800000), C64(0x8000800000800080), C64(0x8000808000800080),
          C64(0x8000000000808000), C64(0x8000008000808000), C64(0x8000000000808080), C64(0x8000008000808080),
          C64(0x8000800000808000), C64(0x8000808000808000), C64(0x8000800000808080), C64(0x8000808000808080),
          C64(0x8080000000800000), C64(0x8080008000800000), C64(0x8080000000800080), C64(0x8080008000800080),
          C64(0x8080800000800000), C64(0x8080808000800000), C64(0x8080800000800080), C64(0x8080808000800080),
          C64(0x8080000000808000), C64(0x8080008000808000), C64(0x8080000000808080), C64(0x8080008000808080),
          C64(0x8080800000808000), C64(0x8080808000808000), C64(0x8080800000808080), C64(0x8080808000808080),
          C64(0x0000000080000000), C64(0x0000008080000000), C64(0x0000000080000080), C64(0x0000008080000080),
          C64(0x0000800080000000), C64(0x0000808080000000), C64(0x0000800080000080), C64(0x0000808080000080),
          C64(0x0000000080008000), C64(0x0000008080008000), C64(0x0000000080008080), C64(0x0000008080008080),
          C64(0x0000800080008000), C64(0x0000808080008000), C64(0x0000800080008080), C64(0x0000808080008080),
          C64(0x0080000080000000), C64(0x0080008080000000), C64(0x0080000080000080), C64(0x0080008080000080),
          C64(0x0080800080000000), C64(0x0080808080000000), C64(0x0080800080000080), C64(0x0080808080000080),
          C64(0x0080000080008000), C64(0x0080008080008000), C64(0x0080000080008080), C64(0x0080008080008080),
          C64(0x0080800080008000), C64(0x0080808080008000), C64(0x0080800080008080), C64(0x0080808080008080),
          C64(0x0000000080800000), C64(0x0000008080800000), C64(0x0000000080800080), C64(0x0000008080800080),
          C64(0x0000800080800000), C64(0x0000808080800000), C64(0x0000800080800080), C64(0x0000808080800080),
          C64(0x0000000080808000), C64(0x0000008080808000), C64(0x0000000080808080), C64(0x0000008080808080),
          C64(0x0000800080808000), C64(0x0000808080808000), C64(0x0000800080808080), C64(0x0000808080808080),
          C64(0x0080000080800000), C64(0x0080008080800000), C64(0x0080000080800080), C64(0x0080008080800080),
          C64(0x0080800080800000), C64(0x0080808080800000), C64(0x0080800080800080), C64(0x0080808080800080),
          C64(0x0080000080808000), C64(0x0080008080808000), C64(0x0080000080808080), C64(0x0080008080808080),
          C64(0x0080800080808000), C64(0x0080808080808000), C64(0x0080800080808080), C64(0x0080808080808080),
          C64(0x8000000080000000), C64(0x8000008080000000), C64(0x8000000080000080), C64(0x8000008080000080),
          C64(0x8000800080000000), C64(0x8000808080000000), C64(0x8000800080000080), C64(0x8000808080000080),
          C64(0x8000000080008000), C64(0x8000008080008000), C64(0x8000000080008080), C64(0x8000008080008080),
          C64(0x8000800080008000), C64(0x8000808080008000), C64(0x8000800080008080), C64(0x8000808080008080),
          C64(0x8080000080000000), C64(0x8080008080000000), C64(0x8080000080000080), C64(0x8080008080000080),
          C64(0x8080800080000000), C64(0x8080808080000000), C64(0x8080800080000080), C64(0x8080808080000080),
          C64(0x8080000080008000), C64(0x8080008080008000), C64(0x8080000080008080), C64(0x8080008080008080),
          C64(0x8080800080008000), C64(0x8080808080008000), C64(0x8080800080008080), C64(0x8080808080008080),
          C64(0x8000000080800000), C64(0x8000008080800000), C64(0x8000000080800080), C64(0x8000008080800080),
          C64(0x8000800080800000), C64(0x8000808080800000), C64(0x8000800080800080), C64(0x8000808080800080),
          C64(0x8000000080808000), C64(0x8000008080808000), C64(0x8000000080808080), C64(0x8000008080808080),
          C64(0x8000800080808000), C64(0x8000808080808000), C64(0x8000800080808080), C64(0x8000808080808080),
          C64(0x8080000080800000), C64(0x8080008080800000), C64(0x8080000080800080), C64(0x8080008080800080),
          C64(0x8080800080800000), C64(0x8080808080800000), C64(0x8080800080800080), C64(0x8080808080800080),
          C64(0x8080000080808000), C64(0x8080008080808000), C64(0x8080000080808080), C64(0x8080008080808080),
          C64(0x8080800080808000), C64(0x8080808080808000), C64(0x8080800080808080), C64(0x8080808080808080)
        },
        { C64(0x0000000000000000), C64(0x0000004000000000), C64(0x0000000000000040), C64(0x0000004000000040),
          C64(0x0000400000000000), C64(0x0000404000000000), C64(0x0000400000000040), C64(0x0000404000000040),
          C64(0x0000000000004000), C64(0x0000004000004000), C64(0x0000000000004040), C64(0x0000004000004040),
          C64(0x0000400000004000), C64(0x0000404000004000), C64(0x0000400000004040), C64(0x0000404000004040),
          C64(0x0040000000000000), C64(0x0040004000000000), C64(0x0040000000000040), C64(0x0040004000000040),
          C64(0x0040400000000000), C64(0x0040404000000000), C64(0x0040400000000040), C64(0x0040404000000040),
          C64(0x0040000000004000), C64(0x0040004000004000), C64(0x0040000000004040), C64(0x0040004000004040),
          C64(0x0040400000004000), C64(0x0040404000004000), C64(0x0040400000004040), C64(0x0040404000004040),
          C64(0x0000000000400000), C64(0x0000004000400000), C64(0x0000000000400040), C64(0x0000004000400040),
          C64(0x0000400000400000), C64(0x0000404000400000), C64(0x0000400000400040), C64(0x0000404000400040),
          C64(0x0000000000404000), C64(0x0000004000404000), C64(0x0000000000404040), C64(0x0000004000404040),
          C64(0x0000400000404000), C64(0x0000404000404000), C64(0x0000400000404040), C64(0x0000404000404040),
          C64(0x0040000000400000), C64(0x0040004000400000), C64(0x0040000000400040), C64(0x0040004000400040),
          C64(0x0040400000400000), C64(0x0040404000400000), C64(0x0040400000400040), C64(0x0040404000400040),
          C64(0x0040000000404000), C64(0x0040004000404000), C64(0x0040000000404040), C64(0x0040004000404040),
          C64(0x0040400000404000), C64(0x0040404000404000), C64(0x0040400000404040), C64(0x0040404000404040),
          C64(0x4000000000000000), C64(0x4000004000000000), C64(0x4000000000000040), C64(0x4000004000000040),
          C64(0x4000400000000000), C64(0x4000404000000000), C64(0x4000400000000040), C64(0x4000404000000040),
          C64(0x4000000000004000), C64(0x4000004000004000), C64(0x4000000000004040), C64(0x4000004000004040),
          C64(0x4000400000004000), C64(0x4000404000004000), C64(0x4000400000004040), C64(0x4000404000004040),
          C64(0x4040000000000000), C64(0x4040004000000000), C64(0x4040000000000040), C64(0x4040004000000040),
          C64(0x4040400000000000), C64(0x4040404000000000), C64(0x4040400000000040), C64(0x4040404000000040),
          C64(0x4040000000004000), C64(0x4040004000004000), C64(0x4040000000004040), C64(0x4040004000004040),
          C64(0x4040400000004000), C64(0x4040404000004000), C64(0x4040400000004040), C64(0x4040404000004040),
          C64(0x4000000000400000), C64(0x4000004000400000), C64(0x4000000000400040), C64(0x4000004000400040),
          C64(0x4000400000400000), C64(0x4000404000400000), C64(0x4000400000400040), C64(0x4000404000400040),
          C64(0x4000000000404000), C64(0x4000004000404000), C64(0x4000000000404040), C64(0x4000004000404040),
          C64(0x4000400000404000), C64(0x4000404000404000), C64(0x4000400000404040), C64(0x4000404000404040),
          C64(0x4040000000400000), C64(0x4040004000400000), C64(0x4040000000400040), C64(0x4040004000400040),
          C64(0x4040400000400000), C64(0x4040404000400000), C64(0x4040400000400040), C64(0x4040404000400040),
          C64(0x4040000000404000), C64(0x4040004000404000), C64(0x4040000000404040), C64(0x4040004000404040),
          C64(0x4040400000404000), C64(0x4040404000404000), C64(0x4040400000404040), C64(0x4040404000404040),
          C64(0x0000000040000000), C64(0x0000004040000000), C64(0x0000000040000040), C64(0x0000004040000040),
          C64(0x0000400040000000), C64(0x0000404040000000), C64(0x0000400040000040), C64(0x0000404040000040),
          C64(0x0000000040004000), C64(0x0000004040004000), C64(0x0000000040004040), C64(0x0000004040004040),
          C64(0x0000400040004000), C64(0x0000404040004000), C64(0x0000400040004040), C64(0x0000404040004040),
          C64(0x0040000040000000), C64(0x0040004040000000), C64(0x0040000040000040), C64(0x0040004040000040),
          C64(0x0040400040000000), C64(0x0040404040000000), C64(0x0040400040000040), C64(0x0040404040000040),
          C64(0x0040000040004000), C64(0x0040004040004000), C64(0x0040000040004040), C64(0x0040004040004040),
          C64(0x0040400040004000), C64(0x0040404040004000), C64(0x0040400040004040), C64(0x0040404040004040),
          C64(0x0000000040400000), C64(0x0000004040400000), C64(0x0000000040400040), C64(0x0000004040400040),
          C64(0x0000400040400000), C64(0x0000404040400000), C64(0x0000400040400040), C64(0x0000404040400040),
          C64(0x0000000040404000), C64(0x0000004040404000), C64(0x0000000040404040), C64(0x0000004040404040),
          C64(0x0000400040404000), C64(0x0000404040404000), C64(0x0000400040404040), C64(0x0000404040404040),
          C64(0x0040000040400000), C64(0x0040004040400000), C64(0x0040000040400040), C64(0x0040004040400040),
          C64(0x0040400040400000), C64(0x0040404040400000), C64(0x0040400040400040), C64(0x0040404040400040),
          C64(0x0040000040404000), C64(0x0040004040404000), C64(0x0040000040404040), C64(0x0040004040404040),
          C64(0x0040400040404000), C64(0x0040404040404000), C64(0x0040400040404040), C64(0x0040404040404040),
          C64(0x4000000040000000), C64(0x4000004040000000), C64(0x4000000040000040), C64(0x4000004040000040),
          C64(0x4000400040000000), C64(0x4000404040000000), C64(0x4000400040000040), C64(0x4000404040000040),
          C64(0x4000000040004000), C64(0x4000004040004000), C64(0x4000000040004040), C64(0x4000004040004040),
          C64(0x4000400040004000), C64(0x4000404040004000), C64(0x4000400040004040), C64(0x4000404040004040),
          C64(0x4040000040000000), C64(0x4040004040000000), C64(0x4040000040000040), C64(0x4040004040000040),
          C64(0x4040400040000000), C64(0x4040404040000000), C64(0x4040400040000040), C64(0x4040404040000040),
          C64(0x4040000040004000), C64(0x4040004040004000), C64(0x4040000040004040), C64(0x4040004040004040),
          C64(0x4040400040004000), C64(0x4040404040004000), C64(0x4040400040004040), C64(0x4040404040004040),
          C64(0x4000000040400000), C64(0x4000004040400000), C64(0x4000000040400040), C64(0x4000004040400040),
          C64(0x4000400040400000), C64(0x4000404040400000), C64(0x4000400040400040), C64(0x4000404040400040),
          C64(0x4000000040404000), C64(0x4000004040404000), C64(0x4000000040404040), C64(0x4000004040404040),
          C64(0x4000400040404000), C64(0x4000404040404000), C64(0x4000400040404040), C64(0x4000404040404040),
          C64(0x4040000040400000), C64(0x4040004040400000), C64(0x4040000040400040), C64(0x4040004040400040),
          C64(0x4040400040400000), C64(0x4040404040400000), C64(0x4040400040400040), C64(0x4040404040400040),
          C64(0x4040000040404000), C64(0x4040004040404000), C64(0x4040000040404040), C64(0x4040004040404040),
          C64(0x4040400040404000), C64(0x4040404040404000), C64(0x4040400040404040), C64(0x4040404040404040)
        },
        { C64(0x0000000000000000), C64(0x0000002000000000), C64(0x0000000000000020), C64(0x0000002000000020),
          C64(0x0000200000000000), C64(0x0000202000000000), C64(0x0000200000000020), C64(0x0000202000000020),
          C64(0x0000000000002000), C64(0x0000002000002000), C64(0x0000000000002020), C64(0x0000002000002020),
          C64(0x0000200000002000), C64(0x0000202000002000), C64(0x0000200000002020), C64(0x0000202000002020),
          C64(0x0020000000000000), C64(0x0020002000000000), C64(0x0020000000000020), C64(0x0020002000000020),
          C64(0x0020200000000000), C64(0x0020202000000000), C64(0x0020200000000020), C64(0x0020202000000020),
          C64(0x0020000000002000), C64(0x0020002000002000), C64(0x0020000000002020), C64(0x0020002000002020),
          C64(0x0020200000002000), C64(0x0020202000002000), C64(0x0020200000002020), C64(0x0020202000002020),
          C64(0x0000000000200000), C64(0x0000002000200000), C64(0x0000000000200020), C64(0x0000002000200020),
          C64(0x0000200000200000), C64(0x0000202000200000), C64(0x0000200000200020), C64(0x0000202000200020),
          C64(0x0000000000202000), C64(0x0000002000202000), C64(0x0000000000202020), C64(0x0000002000202020),
          C64(0x0000200000202000), C64(0x0000202000202000), C64(0x0000200000202020), C64(0x0000202000202020),
          C64(0x0020000000200000), C64(0x0020002000200000), C64(0x0020000000200020), C64(0x0020002000200020),
          C64(0x0020200000200000), C64(0x0020202000200000), C64(0x0020200000200020), C64(0x0020202000200020),
          C64(0x0020000000202000), C64(0x0020002000202000), C64(0x0020000000202020), C64(0x0020002000202020),
          C64(0x0020200000202000), C64(0x0020202000202000), C64(0x0020200000202020), C64(0x0020202000202020),
          C64(0x2000000000000000), C64(0x2000002000000000), C64(0x2000000000000020), C64(0x2000002000000020),
          C64(0x2000200000000000), C64(0x2000202000000000), C64(0x2000200000000020), C64(0x2000202000000020),
          C64(0x2000000000002000), C64(0x2000002000002000), C64(0x2000000000002020), C64(0x2000002000002020),
          C64(0x2000200000002000), C64(0x2000202000002000), C64(0x2000200000002020), C64(0x2000202000002020),
          C64(0x2020000000000000), C64(0x2020002000000000), C64(0x2020000000000020), C64(0x2020002000000020),
          C64(0x2020200000000000), C64(0x2020202000000000), C64(0x2020200000000020), C64(0x2020202000000020),
          C64(0x2020000000002000), C64(0x2020002000002000), C64(0x2020000000002020), C64(0x2020002000002020),
          C64(0x2020200000002000), C64(0x2020202000002000), C64(0x2020200000002020), C64(0x2020202000002020),
          C64(0x2000000000200000), C64(0x2000002000200000), C64(0x2000000000200020), C64(0x2000002000200020),
          C64(0x2000200000200000), C64(0x2000202000200000), C64(0x2000200000200020), C64(0x2000202000200020),
          C64(0x2000000000202000), C64(0x2000002000202000), C64(0x2000000000202020), C64(0x2000002000202020),
          C64(0x2000200000202000), C64(0x2000202000202000), C64(0x2000200000202020), C64(0x2000202000202020),
          C64(0x2020000000200000), C64(0x2020002000200000), C64(0x2020000000200020), C64(0x2020002000200020),
          C64(0x2020200000200000), C64(0x2020202000200000), C64(0x2020200000200020), C64(0x2020202000200020),
          C64(0x2020000000202000), C64(0x2020002000202000), C64(0x2020000000202020), C64(0x2020002000202020),
          C64(0x2020200000202000), C64(0x2020202000202000), C64(0x2020200000202020), C64(0x2020202000202020),
          C64(0x0000000020000000), C64(0x0000002020000000), C64(0x0000000020000020), C64(0x0000002020000020),
          C64(0x0000200020000000), C64(0x0000202020000000), C64(0x0000200020000020), C64(0x0000202020000020),
          C64(0x0000000020002000), C64(0x0000002020002000), C64(0x0000000020002020), C64(0x0000002020002020),
          C64(0x0000200020002000), C64(0x0000202020002000), C64(0x0000200020002020), C64(0x0000202020002020),
          C64(0x0020000020000000), C64(0x0020002020000000), C64(0x0020000020000020), C64(0x0020002020000020),
          C64(0x0020200020000000), C64(0x0020202020000000), C64(0x0020200020000020), C64(0x0020202020000020),
          C64(0x0020000020002000), C64(0x0020002020002000), C64(0x0020000020002020), C64(0x0020002020002020),
          C64(0x0020200020002000), C64(0x0020202020002000), C64(0x0020200020002020), C64(0x0020202020002020),
          C64(0x0000000020200000), C64(0x0000002020200000), C64(0x0000000020200020), C64(0x0000002020200020),
          C64(0x0000200020200000), C64(0x0000202020200000), C64(0x0000200020200020), C64(0x0000202020200020),
          C64(0x0000000020202000), C64(0x0000002020202000), C64(0x0000000020202020), C64(0x0000002020202020),
          C64(0x0000200020202000), C64(0x0000202020202000), C64(0x0000200020202020), C64(0x0000202020202020),
          C64(0x0020000020200000), C64(0x0020002020200000), C64(0x0020000020200020), C64(0x0020002020200020),
          C64(0x0020200020200000), C64(0x0020202020200000), C64(0x0020200020200020), C64(0x0020202020200020),
          C64(0x0020000020202000), C64(0x0020002020202000), C64(0x0020000020202020), C64(0x0020002020202020),
          C64(0x0020200020202000), C64(0x0020202020202000), C64(0x0020200020202020), C64(0x0020202020202020),
          C64(0x2000000020000000), C64(0x2000002020000000), C64(0x2000000020000020), C64(0x2000002020000020),
          C64(0x2000200020000000), C64(0x2000202020000000), C64(0x2000200020000020), C64(0x2000202020000020),
          C64(0x2000000020002000), C64(0x2000002020002000), C64(0x2000000020002020), C64(0x2000002020002020),
          C64(0x2000200020002000), C64(0x2000202020002000), C64(0x2000200020002020), C64(0x2000202020002020),
          C64(0x2020000020000000), C64(0x2020002020000000), C64(0x2020000020000020), C64(0x2020002020000020),
          C64(0x2020200020000000), C64(0x2020202020000000), C64(0x2020200020000020), C64(0x2020202020000020),
          C64(0x2020000020002000), C64(0x2020002020002000), C64(0x2020000020002020), C64(0x2020002020002020),
          C64(0x2020200020002000), C64(0x2020202020002000), C64(0x2020200020002020), C64(0x2020202020002020),
          C64(0x2000000020200000), C64(0x2000002020200000), C64(0x2000000020200020), C64(0x2000002020200020),
          C64(0x2000200020200000), C64(0x2000202020200000), C64(0x2000200020200020), C64(0x2000202020200020),
          C64(0x2000000020202000), C64(0x2000002020202000), C64(0x2000000020202020), C64(0x2000002020202020),
          C64(0x2000200020202000), C64(0x2000202020202000), C64(0x2000200020202020), C64(0x2000202020202020),
          C64(0x2020000020200000), C64(0x2020002020200000), C64(0x2020000020200020), C64(0x2020002020200020),
          C64(0x2020200020200000), C64(0x2020202020200000), C64(0x2020200020200020), C64(0x2020202020200020),
          C64(0x2020000020202000), C64(0x2020002020202000), C64(0x2020000020202020), C64(0x2020002020202020),
          C64(0x2020200020202000), C64(0x2020202020202000), C64(0x2020200020202020), C64(0x2020202020202020)
        }
    };

    static const uint64_t des_fp[8][256] = {
        { C64(0x0000000000000000), C64(0x0000008000000000), C64(0x0000000002000000), C64(0x0000008002000000),
          C64(0x0000000000020000), C64(0x0000008000020000), C64(0x0000000002020000), C64(0x0000008002020000),
          C64(0x0000000000000200), C64(0x0000008000000200), C64(0x0000000002000200), C64(0x0000008002000200),
          C64(0x0000000000020200), C64(0x0000008000020200), C64(0x0000000002020200), C64(0x0000008002020200),
          C64(0x0000000000000002), C64(0x0000008000000002), C64(0x0000000002000002), C64(0x0000008002000002),
          C64(0x0000000000020002), C64(0x0000008000020002), C64(0x0000000002020002), C64(0x0000008002020002),
          C64(0x0000000000000202), C64(0x0000008000000202), C64(0x0000000002000202), C64(0x0000008002000202),
          C64(0x0000000000020202), C64(0x0000008000020202), C64(0x0000000002020202), C64(0x0000008002020202),
          C64(0x0200000000000000), C64(0x0200008000000000), C64(0x0200000002000000), C64(0x0200008002000000),
          C64(0x0200000000020000), C64(0x0200008000020000), C64(0x0200000002020000), C64(0x0200008002020000),
          C64(0x0200000000000200), C64(0x0200008000000200), C64(0x0200000002000200), C64(0x0200008002000200),
          C64(0x0200000000020200), C64(0x0200008000020200), C64(0x0200000002020200), C64(0x0200008002020200),
          C64(0x0200000000000002), C64(0x0200008000000002), C64(0x0200000002000002), C64(0x0200008002000002),
          C64(0x0200000000020002), C64(0x0200008000020002), C64(0x0200000002020002), C64(0x0200008002020002),
          C64(0x0200000000000202), C64(0x0200008000000202), C64(0x0200000002000202), C64(0x0200008002000202),
          C64(0x0200000000020202), C64(0x0200008000020202), C64(0x0200000002020202), C64(0x0200008002020202),
          C64(0x0002000000000000), C64(0x0002008000000000), C64(0x0002000002000000), C64(0x0002008002000000),
          C64(0x0002000000020000), C64(0x0002008000020000), C64(0x0002000002020000), C64(0x0002008002020000),
          C64(0x0002000000000200), C64(0x0002008000000200), C64(0x0002000002000200), C64(0x0002008002000200),
          C64(0x0002000000020200), C64(0x0002008000020200), C64(0x0002000002020200), C64(0x0002008002020200),
          C64(0x0002000000000002), C64(0x0002008000000002), C64(0x0002000002000002), C64(0x0002008002000002),
          C64(0x0002000000020002), C64(0x0002008000020002), C64(0x0002000002020002), C64(0x0002008002020002),
          C64(0x0002000000000202), C64(0x0002008000000202), C64(0x0002000002000202), C64(0x0002008002000202),
          C64(0x0002000000020202), C64(0x0002008000020202), C64(0x0002000002020202), C64(0x0002008002020202),
          C64(0x0202000000000000), C64(0x0202008000000000), C64(0x0202000002000000), C64(0x0202008002000000),
          C64(0x0202000000020000), C64(0x0202008000020000), C64(0x0202000002020000), C64(0x0202008002020000),
          C64(0x0202000000000200), C64(0x0202008000000200), C64(0x0202000002000200), C64(0x0202008002000200),
          C64(0x0202000000020200), C64(0x0202008000020200), C64(0x0202000002020200), C64(0x0202008002020200),
          C64(0x0202000000000002), C64(0x0202008000000002), C64(0x0202000002000002), C64(0x0202008002000002),
          C64(0x0202000000020002), C64(0x0202008000020002), C64(0x0202000002020002), C64(0x0202008002020002),
          C64(0x0202000000000202), C64(0x0202008000000202), C64(0x0202000002000202), C64(0x0202008002000202),
          C64(0x0202000000020202), C64(0x0202008000020202), C64(0x0202000002020202), C64(0x0202008002020202),
          C64(0x0000020000000000), C64(0x0000028000000000), C64(0x0000020002000000), C64(0x0000028002000000),
          C64(0x0000020000020000), C64(0x0000028000020000), C64(0x0000020002020000), C64(0x0000028002020000),
          C64(0x0000020000000200), C64(0x0000028000000200), C64(0x0000020002000200), C64(0x0000028002000200),
          C64(0x0000020000020200), C64(0x0000028000020200), C64(0x0000020002020200), C64(0x0000028002020200),
          C64(0x0000020000000002), C64(0x0000028000000002), C64(0x0000020002000002), C64(0x0000028002000002),
          C64(0x0000020000020002), C64(0x0000028000020002), C64(0x0000020002020002), C64(0x0000028002020002),
          C64(0x0000020000000202), C64(0x0000028000000202), C64(0x0000020002000202), C64(0x0000028002000202),
          C64(0x0000020000020202), C64(0x0000028000020202), C64(0x0000020002020202), C64(0x0000028002020202),
          C64(0x0200020000000000), C64(0x0200028000000000), C64(0x0200020002000000), C64(0x0200028002000000),
          C64(0x0200020000020000), C64(0x0200028000020000), C64(0x0200020002020000), C64(0x0200028002020000),
          C64(0x0200020000000200), C64(0x0200028000000200), C64(0x0200020002000200), C64(0x0200028002000200),
          C64(0x0200020000020200), C64(0x0200028000020200), C64(0x0200020002020200), C64(0x0200028002020200),
          C64(0x0200020000000002), C64(0x0200028000000002), C64(0x0200020002000002), C64(0x0200028002000002),
          C64(0x0200020000020002), C64(0x0200028000020002), C64(0x0200020002020002), C64(0x0200028002020002),
          C64(0x0200020000000202), C64(0x0200028000000202), C64(0x0200020002000202), C64(0x0200028002000202),
          C64(0x0200020000020202), C64(0x0200028000020202), C64(0x0200020002020202), C64(0x0200028002020202),
          C64(0x0002020000000000), C64(0x0002028000000000), C64(0x0002020002000000), C64(0x0002028002000000),
          C64(0x0002020000020000), C64(0x0002028000020000), C64(0x0002020002020000), C64(0x0002028002020000),
          C64(0x0002020000000200), C64(0x0002028000000200), C64(0x0002020002000200), C64(0x0002028002000200),
          C64(0x0002020000020200), C64(0x0002028000020200), C64(0x0002020002020200), C64(0x0002028002020200),
          C64(0x0002020000000002), C64(0x0002028000000002), C64(0x0002020002000002), C64(0x0002028002000002),
          C64(0x0002020000020002), C64(0x0002028000020002), C64(0x0002020002020002), C64(0x0002028002020002),
          C64(0x0002020000000202), C64(0x0002028000000202), C64(0x0002020002000202), C64(0x0002028002000202),
          C64(0x0002020000020202), C64(0x0002028000020202), C64(0x0002020002020202), C64(0x0002028002020202),
          C64(0x0202020000000000), C64(0x0202028000000000), C64(0x0202020002000000), C64(0x0202028002000000),
          C64(0x0202020000020000), C64(0x0202028000020000), C64(0x0202020002020000), C64(0x0202028002020000),
          C64(0x0202020000000200), C64(0x0202028000000200), C64(0x0202020002000200), C64(0x0202028002000200),
          C64(0x0202020000020200), C64(0x0202028000020200), C64(0x0202020002020200), C64(0x0202028002020200),
          C64(0x0202020000000002), C64(0x0202028000000002), C64(0x0202020002000002), C64(0x0202028002000002),
          C64(0x0202020000020002), C64(0x0202028000020002), C64(0x0202020002020002), C64(0x0202028002020002),
          C64(0x0202020000000202), C64(0x0202028000000202), C64(0x0202020002000202), C64(0x0202028002000202),
          C64(0x0202020000020202), C64(0x0202028000020202), C64(0x0202020002020202), C64(0x0202028002020202)
        },
        { C64(0x0000000000000000), C64(0x0000000200000000), C64(0x0000000008000000), C64(0x0000000208000000),
          C64(0x0000000000080000), C64(0x0000000200080000), C64(0x0000000008080000), C64(0x0000000208080000),
          C64(0x0000000000000800), C64(0x0000000200000800), C64(0x0000000008000800), C64(0x0000000208000800),
          C64(0x0000000000080800), C64(0x0000000200080800), C64(0x0000000008080800), C64(0x0000000208080800),
          C64(0x0000000000000008), C64(0x0000000200000008), C64(0x0000000008000008), C64(0x0000000208000008),
          C64(0x0000000000080008), C64(0x0000000200080008), C64(0x0000000008080008), C64(0x0000000208080008),
          C64(0x0000000000000808), C64(0x0000000200000808), C64(0x0000000008000808), C64(0x0000000208000808),
          C64(0x0000000000080808), C64(0x0000000200080808), C64(0x0000000008080808), C64(0x0000000208080808),
          C64(0x0800000000000000), C64(0x0800000200000000), C64(0x0800000008000000), C64(0x0800000208000000),
          C64(0x0800000000080000), C64(0x0800000200080000), C64(0x0800000008080000), C64(0x0800000208080000),
          C64(0x0800000000000800), C64(0x0800000200000800), C64(0x0800000008000800), C64(0x0800000208000800),
          C64(0x0800000000080800), C64(0x0800000200080800), C64(0x0800000008080800), C64(0x0800000208080800),
          C64(0x0800000000000008), C64(0x0800000200000008), C64(0x0800000008000008), C64(0x0800000208000008),
          C64(0x0800000000080008), C64(0x0800000200080008), C64(0x0800000008080008), C64(0x0800000208080008),
          C64(0x0800000000000808), C64(0x0800000200000808), C64(0x0800000008000808), C64(0x0800000208000808),
          C64(0x0800000000080808), C64(0x0800000200080808), C64(0x0800000008080808), C64(0x0800000208080808),
          C64(0x0008000000000000), C64(0x0008000200000000), C64(0x0008000008000000), C64(0x0008000208000000),
          C64(0x0008000000080000), C64(0x0008000200080000), C64(0x0008000008080000), C64(0x0008000208080000),
          C64(0x0008000000000800), C64(0x0008000200000800), C64(0x0008000008000800), C64(0x0008000208000800),
          C64(0x0008000000080800), C64(0x0008000200080800), C64(0x0008000008080800), C64(0x0008000208080800),
          C64(0x0008000000000008), C64(0x0008000200000008), C64(0x0008000008000008), C64(0x0008000208000008),
          C64(0x0008000000080008), C64(0x0008000200080008), C64(0x0008000008080008), C64(0x0008000208080008),
          C64(0x0008000000000808), C64(0x0008000200000808), C64(0x0008000008000808), C64(0x0008000208000808),
          C64(0x0008000000080808), C64(0x0008000200080808), C64(0x0008000008080808), C64(0x0008000208080808),
          C64(0x0808000000000000), C64(0x0808000200000000), C64(0x0808000008000000), C64(0x0808000208000000),
          C64(0x0808000000080000), C64(0x0808000200080000), C64(0x0808000008080000), C64(0x0808000208080000),
          C64(0x0808000000000800), C64(0x0808000200000800), C64(0x0808000008000800), C64(0x0808000208000800),
          C64(0x0808000000080800), C64(0x0808000200080800), C64(0x0808000008080800), C64(0x0808000208080800),
          C64(0x0808000000000008), C64(0x0808000200000008), C64(0x0808000008000008), C64(0x0808000208000008),
          C64(0x0808000000080008), C64(0x0808000200080008), C64(0x0808000008080008), C64(0x0808000208080008),
          C64(0x0808000000000808), C64(0x0808000200000808), C64(0x0808000008000808), C64(0x0808000208000808),
          C64(0x0808000000080808), C64(0x0808000200080808), C64(0x0808000008080808), C64(0x0808000208080808),
          C64(0x0000080000000000), C64(0x0000080200000000), C64(0x0000080008000000), C64(0x0000080208000000),
          C64(0x0000080000080000), C64(0x0000080200080000), C64(0x0000080008080000), C64(0x0000080208080000),
          C64(0x0000080000000800), C64(0x0000080200000800), C64(0x0000080008000800), C64(0x0000080208000800),
          C64(0x0000080000080800), C64(0x0000080200080800), C64(0x0000080008080800), C64(0x0000080208080800),
          C64(0x0000080000000008), C64(0x0000080200000008), C64(0x0000080008000008), C64(0x0000080208000008),
          C64(0x0000080000080008), C64(0x0000080200080008), C64(0x0000080008080008), C64(0x0000080208080008),
          C64(0x0000080000000808), C64(0x0000080200000808), C64(0x0000080008000808), C64(0x0000080208000808),
          C64(0x0000080000080808), C64(0x0000080200080808), C64(0x0000080008080808), C64(0x0000080208080808),
          C64(0x0800080000000000), C64(0x0800080200000000), C64(0x0800080008000000), C64(0x0800080208000000),
          C64(0x0800080000080000), C64(0x0800080200080000), C64(0x0800080008080000), C64(0x0800080208080000),
          C64(0x0800080000000800), C64(0x0800080200000800), C64(0x0800080008000800), C64(0x0800080208000800),
          C64(0x0800080000080800), C64(0x0800080200080800), C64(0x0800080008080800), C64(0x0800080208080800),
          C64(0x0800080000000008), C64(0x0800080200000008), C64(0x0800080008000008), C64(0x0800080208000008),
          C64(0x0800080000080008), C64(0x0800080200080008), C64(0x0800080008080008), C64(0x0800080208080008),
          C64(0x0800080000000808), C64(0x0800080200000808), C64(0x0800080008000808), C64(0x0800080208000808),
          C64(0x0800080000080808), C64(0x0800080200080808), C64(0x0800080008080808), C64(0x0800080208080808),
          C64(0x0008080000000000), C64(0x0008080200000000), C64(0x0008080008000000), C64(0x0008080208000000),
          C64(0x0008080000080000), C64(0x0008080200080000), C64(0x0008080008080000), C64(0x0008080208080000),
          C64(0x0008080000000800), C64(0x0008080200000800), C64(0x0008080008000800), C64(0x0008080208000800),
          C64(0x0008080000080800), C64(0x0008080200080800), C64(0x0008080008080800), C64(0x0008080208080800),
          C64(0x0008080000000008), C64(0x0008080200000008), C64(0x0008080008000008), C64(0x0008080208000008),
          C64(0x0008080000080008), C64(0x0008080200080008), C64(0x0008080008080008), C64(0x0008080208080008),
          C64(0x0008080000000808), C64(0x0008080200000808), C64(0x0008080008000808), C64(0x0008080208000808),
          C64(0x0008080000080808), C64(0x0008080200080808), C64(0x0008080008080808), C64(0x0008080208080808),
          C64(0x0808080000000000), C64(0x0808080200000000), C64(0x0808080008000000), C64(0x0808080208000000),
          C64(0x0808080000080000), C64(0x0808080200080000), C64(0x0808080008080000), C64(0x0808080208080000),
          C64(0x0808080000000800), C64(0x0808080200000800), C64(0x0808080008000800), C64(0x0808080208000800),
          C64(0x0808080000080800), C64(0x0808080200080800), C64(0x0808080008080800), C64(0x0808080208080800),
          C64(0x0808080000000008), C64(0x0808080200000008), C64(0x0808080008000008), C64(0x0808080208000008),
          C64(0x0808080000080008), C64(0x0808080200080008), C64(0x0808080008080008), C64(0x0808080208080008),
          C64(0x0808080000000808), C64(0x0808080200000808), C64(0x0808080008000808), C64(0x0808080208000808),
          C64(0x0808080000080808), C64(0x0808080200080808), C64(0x0808080008080808), C64(0x0808080208080808)
        },
        { C64(0x0000000000000000), C64(0x0000000800000000), C64(0x0000000020000000), C64(0x0000000820000000),
          C64(0x0000000000200000), C64(0x0000000800200000), C64(0x0000000020200000), C64(0x0000000820200000),
          C64(0x0000000000002000), C64(0x0000000800002000), C64(0x0000000020002000), C64(0x0000000820002000),
          C64(0x0000000000202000), C64(0x0000000800202000), C64(0x0000000020202000), C64(0x0000000820202000),
          C64(0x0000000000000020), C64(0x0000000800000020), C64(0x0000000020000020), C64(0x0000000820000020),
          C64(0x0000000000200020), C64(0x0000000800200020), C64(0x0000000020200020), C64(0x0000000820200020),
          C64(0x0000000000002020), C64(0x0000000800002020), C64(0x0000000020002020), C64(0x0000000820002020),
          C64(0x0000000000202020), C64(0x0000000800202020), C64(0x0000000020202020), C64(0x0000000820202020),
          C64(0x2000000000000000), C64(0x2000000800000000), C64(0x2000000020000000), C64(0x2000000820000000),
          C64(0x2000000000200000), C64(0x2000000800200000), C64(0x2000000020200000), C64(0x2000000820200000),
          C64(0x2000000000002000), C64(0x2000000800002000), C64(0x2000000020002000), C64(0x2000000820002000),
          C64(0x2000000000202000), C64(0x2000000800202000), C64(0x2000000020202000), C64(0x2000000820202000),
          C64(0x2000000000000020), C64(0x2000000800000020), C64(0x2000000020000020), C64(0x2000000820000020),
          C64(0x2000000000200020), C64(0x2000000800200020), C64(0x2000000020200020), C64(0x2000000820200020),
          C64(0x2000000000002020), C64(0x2000000800002020), C64(0x2000000020002020), C64(0x2000000820002020),
          C64(0x2000000000202020), C64(0x2000000800202020), C64(0x2000000020202020), C64(0x2000000820202020),
          C64(0x0020000000000000), C64(0x0020000800000000), C64(0x0020000020000000), C64(0x0020000820000000),
          C64(0x0020000000200000), C64(0x0020000800200000), C64(0x0020000020200000), C64(0x0020000820200000),
          C64(0x0020000000002000), C64(0x0020000800002000), C64(0x0020000020002000), C64(0x0020000820002000),
          C64(0x0020000000202000), C64(0x0020000800202000), C64(0x0020000020202000), C64(0x0020000820202000),
          C64(0x0020000000000020), C64(0x0020000800000020), C64(0x0020000020000020), C64(0x0020000820000020),
          C64(0x0020000000200020), C64(0x0020000800200020), C64(0x0020000020200020), C64(0x0020000820200020),
          C64(0x0020000000002020), C64(0x0020000800002020), C64(0x0020000020002020), C64(0x0020000820002020),
          C64(0x0020000000202020), C64(0x0020000800202020), C64(0x0020000020202020), C64(0x0020000820202020),
          C64(0x2020000000000000), C64(0x2020000800000000), C64(0x2020000020000000), C64(0x2020000820000000),
          C64(0x2020000000200000), C64(0x2020000800200000), C64(0x2020000020200000), C64(0x2020000820200000),
          C64(0x2020000000002000), C64(0x2020000800002000), C64(0x2020000020002000), C64(0x2020000820002000),
          C64(0x2020000000202000), C64(0x2020000800202000), C64(0x2020000020202000), C64(0x2020000820202000),
          C64(0x2020000000000020), C64(0x2020000800000020), C64(0x2020000020000020), C64(0x2020000820000020),
          C64(0x2020000000200020), C64(0x2020000800200020), C64(0x2020000020200020), C64(0x2020000820200020),
          C64(0x2020000000002020), C64(0x2020000800002020), C64(0x2020000020002020), C64(0x2020000820002020),
          C64(0x2020000000202020), C64(0x2020000800202020), C64(0x2020000020202020), C64(0x2020000820202020),
          C64(0x0000200000000000), C64(0x0000200800000000), C64(0x0000200020000000), C64(0x0000200820000000),
          C64(0x0000200000200000), C64(0x0000200800200000), C64(0x0000200020200000), C64(0x0000200820200000),
          C64(0x0000200000002000), C64(0x0000200800002000), C64(0x0000200020002000), C64(0x0000200820002000),
          C64(0x0000200000202000), C64(0x0000200800202000), C64(0x0000200020202000), C64(0x0000200820202000),
          C64(0x0000200000000020), C64(0x0000200800000020), C64(0x0000200020000020), C64(0x0000200820000020),
          C64(0x0000200000200020), C64(0x0000200800200020), C64(0x0000200020200020), C64(0x0000200820200020),
          C64(0x0000200000002020), C64(0x0000200800002020), C64(0x0000200020002020), C64(0x0000200820002020),
          C64(0x0000200000202020), C64(0x0000200800202020), C64(0x0000200020202020), C64(0x0000200820202020),
          C64(0x2000200000000000), C64(0x2000200800000000), C64(0x2000200020000000), C64(0x2000200820000000),
          C64(0x2000200000200000), C64(0x2000200800200000), C64(0x2000200020200000), C64(0x2000200820200000),
          C64(0x2000200000002000), C64(0x2000200800002000), C64(0x2000200020002000), C64(0x2000200820002000),
          C64(0x2000200000202000), C64(0x2000200800202000), C64(0x2000200020202000), C64(0x2000200820202000),
          C64(0x2000200000000020), C64(0x2000200800000020), C64(0x2000200020000020), C64(0x2000200820000020),
          C64(0x2000200000200020), C64(0x2000200800200020), C64(0x2000200020200020), C64(0x2000200820200020),
          C64(0x2000200000002020), C64(0x2000200800002020), C64(0x2000200020002020), C64(0x2000200820002020),
          C64(0x2000200000202020), C64(0x2000200800202020), C64(0x2000200020202020), C64(0x2000200820202020),
          C64(0x0020200000000000), C64(0x0020200800000000), C64(0x0020200020000000), C64(0x0020200820000000),
          C64(0x0020200000200000), C64(0x0020200800200000), C64(0x0020200020200000), C64(0x0020200820200000),
          C64(0x0020200000002000), C64(0x0020200800002000), C64(0x0020200020002000), C64(0x0020200820002000),
          C64(0x0020200000202000), C64(0x0020200800202000), C64(0x0020200020202000), C64(0x0020200820202000),
          C64(0x0020200000000020), C64(0x0020200800000020), C64(0x0020200020000020), C64(0x0020200820000020),
          C64(0x0020200000200020), C64(0x0020200800200020), C64(0x0020200020200020), C64(0x0020200820200020),
          C64(0x0020200000002020), C64(0x0020200800002020), C64(0x0020200020002020), C64(0x0020200820002020),
          C64(0x0020200000202020), C64(0x0020200800202020), C64(0x0020200020202020), C64(0x0020200820202020),
          C64(0x2020200000000000), C64(0x2020200800000000), C64(0x2020200020000000), C64(0x2020200820000000),
          C64(0x2020200000200000), C64(0x2020200800200000), C64(0x2020200020200000), C64(0x2020200820200000),
          C64(0x2020200000002000), C64(0x2020200800002000), C64(0x2020200020002000), C64(0x2020200820002000),
          C64(0x2020200000202000), C64(0x2020200800202000), C64(0x2020200020202000), C64(0x2020200820202000),
          C64(0x2020200000000020), C64(0x2020200800000020), C64(0x2020200020000020), C64(0x2020200820000020),
          C64(0x2020200000200020), C64(0x2020200800200020), C64(0x2020200020200020), C64(0x2020200820200020),
          C64(0x2020200000002020), C64(0x2020200800002020), C64(0x2020200020002020), C64(0x2020200820002020),
          C64(0x2020200000202020), C64(0x2020200800202020), C64(0x2020200020202020), C64(0x2020200820202020)
        },
        { C64(0x0000000000000000), C64(0x0000002000000000), C64(0x0000000080000000), C64(0x0000002080000000),
          C64(0x0000000000800000), C64(0x0000002000800000), C64(0x0000000080800000), C64(0x0000002080800000),
          C64(0x0000000000008000), C64(0x0000002000008000), C64(0x0000000080008000), C64(0x0000002080008000),
          C64(0x0000000000808000), C64(0x0000002000808000), C64(0x0000000080808000), C64(0x0000002080808000),
          C64(0x0000000000000080), C64(0x0000002000000080), C64(0x0000000080000080), C64(0x0000002080000080),
          C64(0x0000000000800080), C64(0x0000002000800080), C64(0x0000000080800080), C64(0x0000002080800080),
          C64(0x0000000000008080), C64(0x0000002000008080), C64(0x0000000080008080), C64(0x0000002080008080),
          C64(0x0000000000808080), C64(0x0000002000808080), C64(0x0000000080808080), C64(0x0000002080808080),
          C64(0x8000000000000000), C64(0x8000002000000000), C64(0x8000000080000000), C64(0x8000002080000000),
          C64(0x8000000000800000), C64(0x8000002000800000), C64(0x8000000080800000), C64(0x8000002080800000),
          C64(0x8000000000008000), C64(0x8000002000008000), C64(0x8000000080008000), C64(0x8000002080008000),
          C64(0x8000000000808000), C64(0x8000002000808000), C64(0x8000000080808000), C64(0x8000002080808000),
          C64(0x8000000000000080), C64(0x8000002000000080), C64(0x8000000080000080), C64(0x8000002080000080),
          C64(0x8000000000800080), C64(0x8000002000800080), C64(0x8000000080800080), C64(0x8000002080800080),
          C64(0x8000000000008080), C64(0x8000002000008080), C64(0x8000000080008080), C64(0x8000002080008080),
          C64(0x8000000000808080), C64(0x8000002000808080), C64(0x8000000080808080), C64(0x8000002080808080),
          C64(0x0080000000000000), C64(0x0080002000000000), C64(0x0080000080000000), C64(0x0080002080000000),
          C64(0x0080000000800000), C64(0x0080002000800000), C64(0x0080000080800000), C64(0x0080002080800000),
          C64(0x0080000000008000), C64(0x0080002000008000), C64(0x0080000080008000), C64(0x0080002080008000),
          C64(0x0080000000808000), C64(0x0080002000808000), C64(0x0080000080808000), C64(0x0080002080808000),
          C64(0x0080000000000080), C64(0x0080002000000080), C64(0x0080000080000080), C64(0x0080002080000080),
          C64(0x0080000000800080), C64(0x0080002000800080), C64(0x0080000080800080), C64(0x0080002080800080),
          C64(0x0080000000008080), C64(0x0080002000008080), C64(0x0080000080008080), C64(0x0080002080008080),
          C64(0x0080000000808080), C64(0x0080002000808080), C64(0x0080000080808080), C64(0x0080002080808080),
          C64(0x8080000000000000), C64(0x8080002000000000), C64(0x8080000080000000), C64(0x8080002080000000),
          C64(0x8080000000800000), C64(0x8080002000800000), C64(0x8080000080800000), C64(0x8080002080800000),
          C64(0x8080000000008000), C64(0x8080002000008000), C64(0x8080000080008000), C64(0x8080002080008000),
          C64(0x8080000000808000), C64(0x8080002000808000), C64(0x8080000080808000), C64(0x8080002080808000),
          C64(0x8080000000000080), C64(0x8080002000000080), C64(0x8080000080000080), C64(0x8080002080000080),
          C64(0x8080000000800080), C64(0x8080002000800080), C64(0x8080000080800080), C64(0x8080002080800080),
          C64(0x8080000000008080), C64(0x8080002000008080), C64(0x8080000080008080), C64(0x8080002080008080),
          C64(0x8080000000808080), C64(0x8080002000808080), C64(0x8080000080808080), C64(0x8080002080808080),
          C64(0x0000800000000000), C64(0x0000802000000000), C64(0x0000800080000000), C64(0x0000802080000000),
          C64(0x0000800000800000), C64(0x0000802000800000), C64(0x0000800080800000), C64(0x0000802080800000),
          C64(0x0000800000008000), C64(0x0000802000008000), C64(0x0000800080008000), C64(0x0000802080008000),
          C64(0x0000800000808000), C64(0x0000802000808000), C64(0x0000800080808000), C64(0x0000802080808000),
          C64(0x0000800000000080), C64(0x0000802000000080), C64(0x0000800080000080), C64(0x0000802080000080),
          C64(0x0000800000800080), C64(0x0000802000800080), C64(0x0000800080800080), C64(0x0000802080800080),
          C64(0x0000800000008080), C64(0x0000802000008080), C64(0x0000800080008080), C64(0x0000802080008080),
          C64(0x0000800000808080), C64(0x0000802000808080), C64(0x0000800080808080), C64(0x0000802080808080),
          C64(0x8000800000000000), C64(0x8000802000000000), C64(0x8000800080000000), C64(0x8000802080000000),
          C64(0x8000800000800000), C64(0x8000802000800000), C64(0x8000800080800000), C64(0x8000802080800000),
          C64(0x8000800000008000), C64(0x8000802000008000), C64(0x8000800080008000), C64(0x8000802080008000),
          C64(0x8000800000808000), C64(0x8000802000808000), C64(0x8000800080808000), C64(0x8000802080808000),
          C64(0x8000800000000080), C64(0x8000802000000080), C64(0x8000800080000080), C64(0x8000802080000080),
          C64(0x8000800000800080), C64(0x8000802000800080), C64(0x8000800080800080), C64(0x8000802080800080),
          C64(0x8000800000008080), C64(0x8000802000008080), C64(0x8000800080008080), C64(0x8000802080008080),
          C64(0x8000800000808080), C64(0x8000802000808080), C64(0x8000800080808080), C64(0x8000802080808080),
          C64(0x0080800000000000), C64(0x0080802000000000), C64(0x0080800080000000), C64(0x0080802080000000),
          C64(0x0080800000800000), C64(0x0080802000800000), C64(0x0080800080800000), C64(0x0080802080800000),
          C64(0x0080800000008000), C64(0x0080802000008000), C64(0x0080800080008000), C64(0x0080802080008000),
          C64(0x0080800000808000), C64(0x0080802000808000), C64(0x0080800080808000), C64(0x0080802080808000),
          C64(0x0080800000000080), C64(0x0080802000000080), C64(0x0080800080000080), C64(0x0080802080000080),
          C64(0x0080800000800080), C64(0x0080802000800080), C64(0x0080800080800080), C64(0x0080802080800080),
          C64(0x0080800000008080), C64(0x0080802000008080), C64(0x0080800080008080), C64(0x0080802080008080),
          C64(0x0080800000808080), C64(0x0080802000808080), C64(0x0080800080808080), C64(0x0080802080808080),
          C64(0x8080800000000000), C64(0x8080802000000000), C64(0x8080800080000000), C64(0x8080802080000000),
          C64(0x8080800000800000), C64(0x8080802000800000), C64(0x8080800080800000), C64(0x8080802080800000),
          C64(0x8080800000008000), C64(0x8080802000008000), C64(0x8080800080008000), C64(0x8080802080008000),
          C64(0x8080800000808000), C64(0x8080802000808000), C64(0x8080800080808000), C64(0x8080802080808000),
          C64(0x8080800000000080), C64(0x8080802000000080), C64(0x8080800080000080), C64(0x8080802080000080),
          C64(0x8080800000800080), C64(0x8080802000800080), C64(0x8080800080800080), C64(0x8080802080800080),
          C64(0x8080800000008080), C64(0x8080802000008080), C64(0x8080800080008080), C64(0x8080802080008080),
          C64(0x8080800000808080), C64(0x8080802000808080), C64(0x8080800080808080), C64(0x8080802080808080)
        },
        { C64(0x0000000000000000), C64(0x0000004000000000), C64(0x0000000001000000), C64(0x0000004001000000),
          C64(0x0000000000010000), C64(0x0000004000010000), C64(0x0000000001010000), C64(0x0000004001010000),
          C64(0x0000000000000100), C64(0x0000004000000100), C64(0x0000000001000100), C64(0x0000004001000100),
          C64(0x0000000000010100), C64(0x0000004000010100), C64(0x0000000001010100), C64(0x0000004001010100),
          C64(0x0000000000000001), C64(0x0000004000000001), C64(0x0000000001000001), C64(0x0000004001000001),
          C64(0x0000000000010001), C64(0x0000004000010001), C64(0x0000000001010001), C64(0x0000004001010001),
          C64(0x0000000000000101), C64(0x0000004000000101), C64(0x0000000001000101), C64(0x0000004001000101),
          C64(0x0000000000010101), C64(0x0000004000010101), C64(0x0000000001010101), C64(0x0000004001010101),
          C64(0x0100000000000000), C64(0x0100004000000000), C64(0x0100000001000000), C64(0x0100004001000000),
          C64(0x0100000000010000), C64(0x0100004000010000), C64(0x0100000001010000), C64(0x0100004001010000),
          C64(0x0100000000000100), C64(0x0100004000000100), C64(0x0100000001000100), C64(0x0100004001000100),
          C64(0x0100000000010100), C64(0x0100004000010100), C64(0x0100000001010100), C64(0x0100004001010100),
          C64(0x0100000000000001), C64(0x0100004000000001), C64(0x0100000001000001), C64(0x0100004001000001),
          C64(0x0100000000010001), C64(0x0100004000010001), C64(0x0100000001010001), C64(0x0100004001010001),
          C64(0x0100000000000101), C64(0x0100004000000101), C64(0x0100000001000101), C64(0x0100004001000101),
          C64(0x0100000000010101), C64(0x0100004000010101), C64(0x0100000001010101), C64(0x0100004001010101),
          C64(0x0001000000000000), C64(0x0001004000000000), C64(0x0001000001000000), C64(0x0001004001000000),
          C64(0x0001000000010000), C64(0x0001004000010000), C64(0x0001000001010000), C64(0x0001004001010000),
          C64(0x0001000000000100), C64(0x0001004000000100), C64(0x0001000001000100), C64(0x0001004001000100),
          C64(0x0001000000010100), C64(0x0001004000010100), C64(0x0001000001010100), C64(0x0001004001010100),
          C64(0x0001000000000001), C64(0x0001004000000001), C64(0x0001000001000001), C64(0x0001004001000001),
          C64(0x0001000000010001), C64(0x0001004000010001), C64(0x0001000001010001), C64(0x0001004001010001),
          C64(0x0001000000000101), C64(0x0001004000000101), C64(0x0001000001000101), C64(0x0001004001000101),
          C64(0x0001000000010101), C64(0x0001004000010101), C64(0x0001000001010101), C64(0x0001004001010101),
          C64(0x0101000000000000), C64(0x0101004000000000), C64(0x0101000001000000), C64(0x0101004001000000),
          C64(0x0101000000010000), C64(0x0101004000010000), C64(0x0101000001010000), C64(0x0101004001010000),
          C64(0x0101000000000100), C64(0x0101004000000100), C64(0x0101000001000100), C64(0x0101004001000100),
          C64(0x0101000000010100), C64(0x0101004000010100), C64(0x0101000001010100), C64(0x0101004001010100),
          C64(0x0101000000000001), C64(0x0101004000000001), C64(0x0101000001000001), C64(0x0101004001000001),
          C64(0x0101000000010001), C64(0x0101004000010001), C64(0x0101000001010001), C64(0x0101004001010001),
          C64(0x0101000000000101), C64(0x0101004000000101), C64(0x0101000001000101), C64(0x0101004001000101),
          C64(0x0101000000010101), C64(0x0101004000010101), C64(0x0101000001010101), C64(0x0101004001010101),
          C64(0x0000010000000000), C64(0x0000014000000000), C64(0x0000010001000000), C64(0x0000014001000000),
          C64(0x0000010000010000), C64(0x0000014000010000), C64(0x0000010001010000), C64(0x0000014001010000),
          C64(0x0000010000000100), C64(0x0000014000000100), C64(0x0000010001000100), C64(0x0000014001000100),
          C64(0x0000010000010100), C64(0x0000014000010100), C64(0x0000010001010100), C64(0x0000014001010100),
          C64(0x0000010000000001), C64(0x0000014000000001), C64(0x0000010001000001), C64(0x0000014001000001),
          C64(0x0000010000010001), C64(0x0000014000010001), C64(0x0000010001010001), C64(0x0000014001010001),
          C64(0x0000010000000101), C64(0x0000014000000101), C64(0x0000010001000101), C64(0x0000014001000101),
          C64(0x0000010000010101), C64(0x0000014000010101), C64(0x0000010001010101), C64(0x0000014001010101),
          C64(0x0100010000000000), C64(0x0100014000000000), C64(0x0100010001000000), C64(0x0100014001000000),
          C64(0x0100010000010000), C64(0x0100014000010000), C64(0x0100010001010000), C64(0x0100014001010000),
          C64(0x0100010000000100), C64(0x0100014000000100), C64(0x0100010001000100), C64(0x0100014001000100),
          C64(0x0100010000010100), C64(0x0100014000010100), C64(0x0100010001010100), C64(0x0100014001010100),
          C64(0x0100010000000001), C64(0x0100014000000001), C64(0x0100010001000001), C64(0x0100014001000001),
          C64(0x0100010000010001), C64(0x0100014000010001), C64(0x0100010001010001), C64(0x0100014001010001),
          C64(0x0100010000000101), C64(0x0100014000000101), C64(0x0100010001000101), C64(0x0100014001000101),
          C64(0x0100010000010101), C64(0x0100014000010101), C64(0x0100010001010101), C64(0x0100014001010101),
          C64(0x0001010000000000), C64(0x0001014000000000), C64(0x0001010001000000), C64(0x0001014001000000),
          C64(0x0001010000010000), C64(0x0001014000010000), C64(0x0001010001010000), C64(0x0001014001010000),
          C64(0x0001010000000100), C64(0x0001014000000100), C64(0x0001010001000100), C64(0x0001014001000100),
          C64(0x0001010000010100), C64(0x0001014000010100), C64(0x0001010001010100), C64(0x0001014001010100),
          C64(0x0001010000000001), C64(0x0001014000000001), C64(0x0001010001000001), C64(0x0001014001000001),
          C64(0x0001010000010001), C64(0x0001014000010001), C64(0x0001010001010001), C64(0x0001014001010001),
          C64(0x0001010000000101), C64(0x0001014000000101), C64(0x0001010001000101), C64(0x0001014001000101),
          C64(0x0001010000010101), C64(0x0001014000010101), C64(0x0001010001010101), C64(0x0001014001010101),
          C64(0x0101010000000000), C64(0x0101014000000000), C64(0x0101010001000000), C64(0x0101014001000000),
          C64(0x0101010000010000), C64(0x0101014000010000), C64(0x0101010001010000), C64(0x0101014001010000),
          C64(0x0101010000000100), C64(0x0101014000000100), C64(0x0101010001000100), C64(0x0101014001000100),
          C64(0x0101010000010100), C64(0x0101014000010100), C64(0x0101010001010100), C64(0x0101014001010100),
          C64(0x0101010000000001), C64(0x0101014000000001), C64(0x0101010001000001), C64(0x0101014001000001),
          C64(0x0101010000010001), C64(0x0101014000010001), C64(0x0101010001010001), C64(0x0101014001010001),
          C64(0x0101010000000101), C64(0x0101014000000101), C64(0x0101010001000101), C64(0x0101014001000101),
          C64(0x0101010000010101), C64(0x0101014000010101), C64(0x0101010001010101), C64(0x0101014001010101)
        },
        { C64(0x0000000000000000), C64(0x0000000100000000), C64(0x0000000004000000), C64(0x0000000104000000),
          C64(0x0000000000040000), C64(0x0000000100040000), C64(0x0000000004040000), C64(0x0000000104040000),
          C64(0x0000000000000400), C64(0x0000000100000400), C64(0x0000000004000400), C64(0x0000000104000400),
          C64(0x0000000000040400), C64(0x0000000100040400), C64(0x0000000004040400), C64(0x0000000104040400),
          C64(0x0000000000000004), C64(0x0000000100000004), C64(0x0000000004000004), C64(0x0000000104000004),
          C64(0x0000000000040004), C64(0x0000000100040004), C64(0x0000000004040004), C64(0x0000000104040004),
          C64(0x0000000000000404), C64(0x0000000100000404), C64(0x0000000004000404), C64(0x0000000104000404),
          C64(0x0000000000040404), C64(0x0000000100040404), C64(0x0000000004040404), C64(0x0000000104040404),
          C64(0x0400000000000000), C64(0x0400000100000000), C64(0x0400000004000000), C64(0x0400000104000000),
          C64(0x0400000000040000), C64(0x0400000100040000), C64(0x0400000004040000), C64(0x0400000104040000),
          C64(0x0400000000000400), C64(0x0400000100000400), C64(0x0400000004000400), C64(0x0400000104000400),
          C64(0x0400000000040400), C64(0x0400000100040400), C64(0x0400000004040400), C64(0x0400000104040400),
          C64(0x0400000000000004), C64(0x0400000100000004), C64(0x0400000004000004), C64(0x0400000104000004),
          C64(0x0400000000040004), C64(0x0400000100040004), C64(0x0400000004040004), C64(0x0400000104040004),
          C64(0x0400000000000404), C64(0x0400000100000404), C64(0x0400000004000404), C64(0x0400000104000404),
          C64(0x0400000000040404), C64(0x0400000100040404), C64(0x0400000004040404), C64(0x0400000104040404),
          C64(0x0004000000000000), C64(0x0004000100000000), C64(0x0004000004000000), C64(0x0004000104000000),
          C64(0x0004000000040000), C64(0x0004000100040000), C64(0x0004000004040000), C64(0x0004000104040000),
          C64(0x0004000000000400), C64(0x0004000100000400), C64(0x0004000004000400), C64(0x0004000104000400),
          C64(0x0004000000040400), C64(0x0004000100040400), C64(0x0004000004040400), C64(0x0004000104040400),
          C64(0x0004000000000004), C64(0x0004000100000004), C64(0x0004000004000004), C64(0x0004000104000004),
          C64(0x0004000000040004), C64(0x0004000100040004), C64(0x0004000004040004), C64(0x0004000104040004),
          C64(0x0004000000000404), C64(0x0004000100000404), C64(0x0004000004000404), C64(0x0004000104000404),
          C64(0x0004000000040404), C64(0x0004000100040404), C64(0x0004000004040404), C64(0x0004000104040404),
          C64(0x0404000000000000), C64(0x0404000100000000), C64(0x0404000004000000), C64(0x0404000104000000),
          C64(0x0404000000040000), C64(0x0404000100040000), C64(0x0404000004040000), C64(0x0404000104040000),
          C64(0x0404000000000400), C64(0x0404000100000400), C64(0x0404000004000400), C64(0x0404000104000400),
          C64(0x0404000000040400), C64(0x0404000100040400), C64(0x0404000004040400), C64(0x0404000104040400),
          C64(0x0404000000000004), C64(0x0404000100000004), C64(0x0404000004000004), C64(0x0404000104000004),
          C64(0x0404000000040004), C64(0x0404000100040004), C64(0x0404000004040004), C64(0x0404000104040004),
          C64(0x0404000000000404), C64(0x0404000100000404), C64(0x0404000004000404), C64(0x0404000104000404),
          C64(0x0404000000040404), C64(0x0404000100040404), C64(0x0404000004040404), C64(0x0404000104040404),
          C64(0x0000040000000000), C64(0x0000040100000000), C64(0x0000040004000000), C64(0x0000040104000000),
          C64(0x0000040000040000), C64(0x0000040100040000), C64(0x0000040004040000), C64(0x0000040104040000),
          C64(0x0000040000000400), C64(0x0000040100000400), C64(0x0000040004000400), C64(0x0000040104000400),
          C64(0x0000040000040400), C64(0x0000040100040400), C64(0x0000040004040400), C64(0x0000040104040400),
          C64(0x0000040000000004), C64(0x0000040100000004), C64(0x0000040004000004), C64(0x0000040104000004),
          C64(0x0000040000040004), C64(0x0000040100040004), C64(0x0000040004040004), C64(0x0000040104040004),
          C64(0x0000040000000404), C64(0x0000040100000404), C64(0x0000040004000404), C64(0x0000040104000404),
          C64(0x0000040000040404), C64(0x0000040100040404), C64(0x0000040004040404), C64(0x0000040104040404),
          C64(0x0400040000000000), C64(0x0400040100000000), C64(0x0400040004000000), C64(0x0400040104000000),
          C64(0x0400040000040000), C64(0x0400040100040000), C64(0x0400040004040000), C64(0x0400040104040000),
          C64(0x0400040000000400), C64(0x0400040100000400), C64(0x0400040004000400), C64(0x0400040104000400),
          C64(0x0400040000040400), C64(0x0400040100040400), C64(0x0400040004040400), C64(0x0400040104040400),
          C64(0x0400040000000004), C64(0x0400040100000004), C64(0x0400040004000004), C64(0x0400040104000004),
          C64(0x0400040000040004), C64(0x0400040100040004), C64(0x0400040004040004), C64(0x0400040104040004),
          C64(0x0400040000000404), C64(0x0400040100000404), C64(0x0400040004000404), C64(0x0400040104000404),
          C64(0x0400040000040404), C64(0x0400040100040404), C64(0x0400040004040404), C64(0x0400040104040404),
          C64(0x0004040000000000), C64(0x0004040100000000), C64(0x0004040004000000), C64(0x0004040104000000),
          C64(0x0004040000040000), C64(0x0004040100040000), C64(0x0004040004040000), C64(0x0004040104040000),
          C64(0x0004040000000400), C64(0x0004040100000400), C64(0x0004040004000400), C64(0x0004040104000400),
          C64(0x0004040000040400), C64(0x0004040100040400), C64(0x0004040004040400), C64(0x0004040104040400),
          C64(0x0004040000000004), C64(0x0004040100000004), C64(0x0004040004000004), C64(0x0004040104000004),
          C64(0x0004040000040004), C64(0x0004040100040004), C64(0x0004040004040004), C64(0x0004040104040004),
          C64(0x0004040000000404), C64(0x0004040100000404), C64(0x0004040004000404), C64(0x0004040104000404),
          C64(0x0004040000040404), C64(0x0004040100040404), C64(0x0004040004040404), C64(0x0004040104040404),
          C64(0x0404040000000000), C64(0x0404040100000000), C64(0x0404040004000000), C64(0x0404040104000000),
          C64(0x0404040000040000), C64(0x0404040100040000), C64(0x0404040004040000), C64(0x0404040104040000),
          C64(0x0404040000000400), C64(0x0404040100000400), C64(0x0404040004000400), C64(0x0404040104000400),
          C64(0x0404040000040400), C64(0x0404040100040400), C64(0x0404040004040400), C64(0x0404040104040400),
          C64(0x0404040000000004), C64(0x0404040100000004), C64(0x0404040004000004), C64(0x0404040104000004),
          C64(0x0404040000040004), C64(0x0404040100040004), C64(0x0404040004040004), C64(0x0404040104040004),
          C64(0x0404040000000404), C64(0x0404040100000404), C64(0x0404040004000404), C64(0x0404040104000404),
          C64(0x0404040000040404), C64(0x0404040100040404), C64(0x0404040004040404), C64(0x0404040104040404)
        },
        { C64(0x0000000000000000), C64(0x0000000400000000), C64(0x0000000010000000), C64(0x0000000410000000),
          C64(0x0000000000100000), C64(0x0000000400100000), C64(0x0000000010100000), C64(0x0000000410100000),
          C64(0x0000000000001000), C64(0x0000000400001000), C64(0x0000000010001000), C64(0x0000000410001000),
          C64(0x0000000000101000), C64(0x0000000400101000), C64(0x0000000010101000), C64(0x0000000410101000),
          C64(0x0000000000000010), C64(0x0000000400000010), C64(0x0000000010000010), C64(0x0000000410000010),
          C64(0x0000000000100010), C64(0x0000000400100010), C64(0x0000000010100010), C64(0x0000000410100010),
          C64(0x0000000000001010), C64(0x0000000400001010), C64(0x0000000010001010), C64(0x0000000410001010),
          C64(0x0000000000101010), C64(0x0000000400101010), C64(0x0000000010101010), C64(0x0000000410101010),
          C64(0x1000000000000000), C64(0x1000000400000000), C64(0x1000000010000000), C64(0x1000000410000000),
          C64(0x1000000000100000), C64(0x1000000400100000), C64(0x1000000010100000), C64(0x1000000410100000),
          C64(0x1000000000001000), C64(0x1000000400001000), C64(0x1000000010001000), C64(0x1000000410001000),
          C64(0x1000000000101000), C64(0x1000000400101000), C64(0x1000000010101000), C64(0x1000000410101000),
          C64(0x1000000000000010), C64(0x1000000400000010), C64(0x1000000010000010), C64(0x1000000410000010),
          C64(0x1000000000100010), C64(0x1000000400100010), C64(0x1000000010100010), C64(0x1000000410100010),
          C64(0x1000000000001010), C64(0x1000000400001010), C64(0x1000000010001010), C64(0x1000000410001010),
          C64(0x1000000000101010), C64(0x1000000400101010), C64(0x1000000010101010), C64(0x1000000410101010),
          C64(0x0010000000000000), C64(0x0010000400000000), C64(0x0010000010000000), C64(0x0010000410000000),
          C64(0x0010000000100000), C64(0x0010000400100000), C64(0x0010000010100000), C64(0x0010000410100000),
          C64(0x0010000000001000), C64(0x0010000400001000), C64(0x0010000010001000), C64(0x0010000410001000),
          C64(0x0010000000101000), C64(0x0010000400101000), C64(0x0010000010101000), C64(0x0010000410101000),
          C64(0x0010000000000010), C64(0x0010000400000010), C64(0x0010000010000010), C64(0x0010000410000010),
          C64(0x0010000000100010), C64(0x0010000400100010), C64(0x0010000010100010), C64(0x0010000410100010),
          C64(0x0010000000001010), C64(0x0010000400001010), C64(0x0010000010001010), C64(0x0010000410001010),
          C64(0x0010000000101010), C64(0x0010000400101010), C64(0x0010000010101010), C64(0x0010000410101010),
          C64(0x1010000000000000), C64(0x1010000400000000), C64(0x1010000010000000), C64(0x1010000410000000),
          C64(0x1010000000100000), C64(0x1010000400100000), C64(0x1010000010100000), C64(0x1010000410100000),
          C64(0x1010000000001000), C64(0x1010000400001000), C64(0x1010000010001000), C64(0x1010000410001000),
          C64(0x1010000000101000), C64(0x1010000400101000), C64(0x1010000010101000), C64(0x1010000410101000),
          C64(0x1010000000000010), C64(0x1010000400000010), C64(0x1010000010000010), C64(0x1010000410000010),
          C64(0x1010000000100010), C64(0x1010000400100010), C64(0x1010000010100010), C64(0x1010000410100010),
          C64(0x1010000000001010), C64(0x1010000400001010), C64(0x1010000010001010), C64(0x1010000410001010),
          C64(0x1010000000101010), C64(0x1010000400101010), C64(0x1010000010101010), C64(0x1010000410101010),
          C64(0x0000100000000000), C64(0x0000100400000000), C64(0x0000100010000000), C64(0x0000100410000000),
          C64(0x0000100000100000), C64(0x0000100400100000), C64(0x0000100010100000), C64(0x0000100410100000),
          C64(0x0000100000001000), C64(0x0000100400001000), C64(0x0000100010001000), C64(0x0000100410001000),
          C64(0x0000100000101000), C64(0x0000100400101000), C64(0x0000100010101000), C64(0x0000100410101000),
          C64(0x0000100000000010), C64(0x0000100400000010), C64(0x0000100010000010), C64(0x0000100410000010),
          C64(0x0000100000100010), C64(0x0000100400100010), C64(0x0000100010100010), C64(0x0000100410100010),
          C64(0x0000100000001010), C64(0x0000100400001010), C64(0x0000100010001010), C64(0x0000100410001010),
          C64(0x0000100000101010), C64(0x0000100400101010), C64(0x0000100010101010), C64(0x0000100410101010),
          C64(0x1000100000000000), C64(0x1000100400000000), C64(0x1000100010000000), C64(0x1000100410000000),
          C64(0x1000100000100000), C64(0x1000100400100000), C64(0x1000100010100000), C64(0x1000100410100000),
          C64(0x1000100000001000), C64(0x1000100400001000), C64(0x1000100010001000), C64(0x1000100410001000),
          C64(0x1000100000101000), C64(0x1000100400101000), C64(0x1000100010101000), C64(0x1000100410101000),
          C64(0x1000100000000010), C64(0x1000100400000010), C64(0x1000100010000010), C64(0x1000100410000010),
          C64(0x1000100000100010), C64(0x1000100400100010), C64(0x1000100010100010), C64(0x1000100410100010),
          C64(0x1000100000001010), C64(0x1000100400001010), C64(0x1000100010001010), C64(0x1000100410001010),
          C64(0x1000100000101010), C64(0x1000100400101010), C64(0x1000100010101010), C64(0x1000100410101010),
          C64(0x0010100000000000), C64(0x0010100400000000), C64(0x0010100010000000), C64(0x0010100410000000),
          C64(0x0010100000100000), C64(0x0010100400100000), C64(0x0010100010100000), C64(0x0010100410100000),
          C64(0x0010100000001000), C64(0x0010100400001000), C64(0x0010100010001000), C64(0x0010100410001000),
          C64(0x0010100000101000), C64(0x0010100400101000), C64(0x0010100010101000), C64(0x0010100410101000),
          C64(0x0010100000000010), C64(0x0010100400000010), C64(0x0010100010000010), C64(0x0010100410000010),
          C64(0x0010100000100010), C64(0x0010100400100010), C64(0x0010100010100010), C64(0x0010100410100010),
          C64(0x0010100000001010), C64(0x0010100400001010), C64(0x0010100010001010), C64(0x0010100410001010),
          C64(0x0010100000101010), C64(0x0010100400101010), C64(0x0010100010101010), C64(0x0010100410101010),
          C64(0x1010100000000000), C64(0x1010100400000000), C64(0x1010100010000000), C64(0x1010100410000000),
          C64(0x1010100000100000), C64(0x1010100400100000), C64(0x1010100010100000), C64(0x1010100410100000),
          C64(0x1010100000001000), C64(0x1010100400001000), C64(0x1010100010001000), C64(0x1010100410001000),
          C64(0x1010100000101000), C64(0x1010100400101000), C64(0x1010100010101000), C64(0x1010100410101000),
          C64(0x1010100000000010), C64(0x1010100400000010), C64(0x1010100010000010), C64(0x1010100410000010),
          C64(0x1010100000100010), C64(0x1010100400100010), C64(0x1010100010100010), C64(0x1010100410100010),
          C64(0x1010100000001010), C64(0x1010100400001010), C64(0x1010100010001010), C64(0x1010100410001010),
          C64(0x1010100000101010), C64(0x1010100400101010), C64(0x1010100010101010), C64(0x1010100410101010)
        },
        { C64(0x0000000000000000), C64(0x0000001000000000), C64(0x0000000040000000), C64(0x0000001040000000),
          C64(0x0000000000400000), C64(0x0000001000400000), C64(0x0000000040400000), C64(0x0000001040400000),
          C64(0x0000000000004000), C64(0x0000001000004000), C64(0x0000000040004000), C64(0x0000001040004000),
          C64(0x0000000000404000), C64(0x0000001000404000), C64(0x0000000040404000), C64(0x0000001040404000),
          C64(0x0000000000000040), C64(0x0000001000000040), C64(0x0000000040000040), C64(0x0000001040000040),
          C64(0x0000000000400040), C64(0x0000001000400040), C64(0x0000000040400040), C64(0x0000001040400040),
          C64(0x0000000000004040), C64(0x0000001000004040), C64(0x0000000040004040), C64(0x0000001040004040),
          C64(0x0000000000404040), C64(0x0000001000404040), C64(0x0000000040404040), C64(0x0000001040404040),
          C64(0x4000000000000000), C64(0x4000001000000000), C64(0x4000000040000000), C64(0x4000001040000000),
          C64(0x4000000000400000), C64(0x4000001000400000), C64(0x4000000040400000), C64(0x4000001040400000),
          C64(0x4000000000004000), C64(0x4000001000004000), C64(0x4000000040004000), C64(0x4000001040004000),
          C64(0x4000000000404000), C64(0x4000001000404000), C64(0x4000000040404000), C64(0x4000001040404000),
          C64(0x4000000000000040), C64(0x4000001000000040), C64(0x4000000040000040), C64(0x4000001040000040),
          C64(0x4000000000400040), C64(0x4000001000400040), C64(0x4000000040400040), C64(0x4000001040400040),
          C64(0x4000000000004040), C64(0x4000001000004040), C64(0x4000000040004040), C64(0x4000001040004040),
          C64(0x4000000000404040), C64(0x4000001000404040), C64(0x4000000040404040), C64(0x4000001040404040),
          C64(0x0040000000000000), C64(0x0040001000000000), C64(0x0040000040000000), C64(0x0040001040000000),
          C64(0x0040000000400000), C64(0x0040001000400000), C64(0x0040000040400000), C64(0x0040001040400000),
          C64(0x0040000000004000), C64(0x0040001000004000), C64(0x0040000040004000), C64(0x0040001040004000),
          C64(0x0040000000404000), C64(0x0040001000404000), C64(0x0040000040404000), C64(0x0040001040404000),
          C64(0x0040000000000040), C64(0x0040001000000040), C64(0x0040000040000040), C64(0x0040001040000040),
          C64(0x0040000000400040), C64(0x0040001000400040), C64(0x0040000040400040), C64(0x0040001040400040),
          C64(0x0040000000004040), C64(0x0040001000004040), C64(0x0040000040004040), C64(0x0040001040004040),
          C64(0x0040000000404040), C64(0x0040001000404040), C64(0x0040000040404040), C64(0x0040001040404040),
          C64(0x4040000000000000), C64(0x4040001000000000), C64(0x4040000040000000), C64(0x4040001040000000),
          C64(0x4040000000400000), C64(0x4040001000400000), C64(0x4040000040400000), C64(0x4040001040400000),
          C64(0x4040000000004000), C64(0x4040001000004000), C64(0x4040000040004000), C64(0x4040001040004000),
          C64(0x4040000000404000), C64(0x4040001000404000), C64(0x4040000040404000), C64(0x4040001040404000),
          C64(0x4040000000000040), C64(0x4040001000000040), C64(0x4040000040000040), C64(0x4040001040000040),
          C64(0x4040000000400040), C64(0x4040001000400040), C64(0x4040000040400040), C64(0x4040001040400040),
          C64(0x4040000000004040), C64(0x4040001000004040), C64(0x4040000040004040), C64(0x4040001040004040),
          C64(0x4040000000404040), C64(0x4040001000404040), C64(0x4040000040404040), C64(0x4040001040404040),
          C64(0x0000400000000000), C64(0x0000401000000000), C64(0x0000400040000000), C64(0x0000401040000000),
          C64(0x0000400000400000), C64(0x0000401000400000), C64(0x0000400040400000), C64(0x0000401040400000),
          C64(0x0000400000004000), C64(0x0000401000004000), C64(0x0000400040004000), C64(0x0000401040004000),
          C64(0x0000400000404000), C64(0x0000401000404000), C64(0x0000400040404000), C64(0x0000401040404000),
          C64(0x0000400000000040), C64(0x0000401000000040), C64(0x0000400040000040), C64(0x0000401040000040),
          C64(0x0000400000400040), C64(0x0000401000400040), C64(0x0000400040400040), C64(0x0000401040400040),
          C64(0x0000400000004040), C64(0x0000401000004040), C64(0x0000400040004040), C64(0x0000401040004040),
          C64(0x0000400000404040), C64(0x0000401000404040), C64(0x0000400040404040), C64(0x0000401040404040),
          C64(0x4000400000000000), C64(0x4000401000000000), C64(0x4000400040000000), C64(0x4000401040000000),
          C64(0x4000400000400000), C64(0x4000401000400000), C64(0x4000400040400000), C64(0x4000401040400000),
          C64(0x4000400000004000), C64(0x4000401000004000), C64(0x4000400040004000), C64(0x4000401040004000),
          C64(0x4000400000404000), C64(0x4000401000404000), C64(0x4000400040404000), C64(0x4000401040404000),
          C64(0x4000400000000040), C64(0x4000401000000040), C64(0x4000400040000040), C64(0x4000401040000040),
          C64(0x4000400000400040), C64(0x4000401000400040), C64(0x4000400040400040), C64(0x4000401040400040),
          C64(0x4000400000004040), C64(0x4000401000004040), C64(0x4000400040004040), C64(0x4000401040004040),
          C64(0x4000400000404040), C64(0x4000401000404040), C64(0x4000400040404040), C64(0x4000401040404040),
          C64(0x0040400000000000), C64(0x0040401000000000), C64(0x0040400040000000), C64(0x0040401040000000),
          C64(0x0040400000400000), C64(0x0040401000400000), C64(0x0040400040400000), C64(0x0040401040400000),
          C64(0x0040400000004000), C64(0x0040401000004000), C64(0x0040400040004000), C64(0x0040401040004000),
          C64(0x0040400000404000), C64(0x0040401000404000), C64(0x0040400040404000), C64(0x0040401040404000),
          C64(0x0040400000000040), C64(0x0040401000000040), C64(0x0040400040000040), C64(0x0040401040000040),
          C64(0x0040400000400040), C64(0x0040401000400040), C64(0x0040400040400040), C64(0x0040401040400040),
          C64(0x0040400000004040), C64(0x0040401000004040), C64(0x0040400040004040), C64(0x0040401040004040),
          C64(0x0040400000404040), C64(0x0040401000404040), C64(0x0040400040404040), C64(0x0040401040404040),
          C64(0x4040400000000000), C64(0x4040401000000000), C64(0x4040400040000000), C64(0x4040401040000000),
          C64(0x4040400000400000), C64(0x4040401000400000), C64(0x4040400040400000), C64(0x4040401040400000),
          C64(0x4040400000004000), C64(0x4040401000004000), C64(0x4040400040004000), C64(0x4040401040004000),
          C64(0x4040400000404000), C64(0x4040401000404000), C64(0x4040400040404000), C64(0x4040401040404000),
          C64(0x4040400000000040), C64(0x4040401000000040), C64(0x4040400040000040), C64(0x4040401040000040),
          C64(0x4040400000400040), C64(0x4040401000400040), C64(0x4040400040400040), C64(0x4040401040400040),
          C64(0x4040400000004040), C64(0x4040401000004040), C64(0x4040400040004040), C64(0x4040401040004040),
          C64(0x4040400000404040), C64(0x4040401000404040), C64(0x4040400040404040), C64(0x4040401040404040)
        }
    };
}


//----------------------------------------------------------------------------

void ts::DES::cookey(const uint32_t* raw1, uint32_t* keyout)
{
    uint32_t* cook;
    const uint32_t* raw0;
    uint32_t dough[32];
    int i;

    cook = dough;
    for (i=0; i < 16; i++, raw1++) {
        raw0 = raw1++;
        *cook    = uint32_t((*raw0 & 0x00FC0000L) << 6);
        *cook   |= uint32_t((*raw0 & 0x00000FC0L) << 10);
        *cook   |= uint32_t((*raw1 & 0x00FC0000L) >> 10);
        *cook++ |= uint32_t((*raw1 & 0x00000FC0L) >> 6);
        *cook    = uint32_t((*raw0 & 0x0003F000L) << 12);
        *cook   |= uint32_t((*raw0 & 0x0000003FL) << 16);
        *cook   |= uint32_t((*raw1 & 0x0003F000L) >> 4);
        *cook++ |= (*raw1 & 0x0000003FL);
    }

    // Flawfinder: ignore: memcpy()
    ::memcpy(keyout, dough, sizeof(dough));
}


//----------------------------------------------------------------------------

void ts::DES::deskey(const uint8_t* key, uint16_t edf, uint32_t* keyout)
{
    uint32_t i, j, l, m, n, kn[32];
    uint8_t pc1m[56], pcr[56];

    for (j=0; j < 56; j++) {
        l = uint32_t(pc1[j]);
        m = l & 7;
        pc1m[j] = uint8_t((key[l >> 3U] & bytebit[m]) == bytebit[m] ? 1 : 0);
    }

    for (i=0; i < 16; i++) {
        if (edf == DE1) {
            m = (15 - i) << 1;
        }
        else {
            m = i << 1;
        }
        n = m + 1;
        kn[m] = kn[n] = 0L;
        for (j = 0; j < 28; j++) {
            l = j + uint32_t(totrot[i]);
            if (l < 28) {
                pcr[j] = pc1m[l];
            }
            else {
                pcr[j] = pc1m[l - 28];
            }
        }
        for (/*j = 28*/; j < 56; j++) {
            l = j + uint32_t (totrot[i]);
            if (l < 56) {
                pcr[j] = pc1m[l];
            }
            else {
                pcr[j] = pc1m[l - 28];
            }
        }
        for (j = 0; j < 24; j++)  {
            if (pcr[pc2[j]] != 0) {
                kn[m] |= bigbyte[j];
            }
            if (pcr[pc2[j+24]] != 0) {
                kn[n] |= bigbyte[j];
            }
        }
    }

    cookey(kn, keyout);
}


//----------------------------------------------------------------------------

void ts::DES::desfunc(uint32_t* block, const uint32_t* keys)
{
    uint32_t work, right, leftt;
    uint64_t tmp;
    int cur_round;

    leftt = block[0];
    right = block[1];

    tmp = des_ip[0][BYTE (leftt, 0)] ^
          des_ip[1][BYTE (leftt, 1)] ^
          des_ip[2][BYTE (leftt, 2)] ^
          des_ip[3][BYTE (leftt, 3)] ^
          des_ip[4][BYTE (right, 0)] ^
          des_ip[5][BYTE (right, 1)] ^
          des_ip[6][BYTE (right, 2)] ^
          des_ip[7][BYTE (right, 3)];

    leftt = uint32_t (tmp >> 32);
    right = uint32_t (tmp & 0xFFFFFFFFUL);

    for (cur_round = 0; cur_round < 8; cur_round++) {
        work  = RORc(right, 4) ^ *keys++;
        leftt ^= SP7[work        & 0x3fL]
              ^ SP5[(work >>  8) & 0x3fL]
              ^ SP3[(work >> 16) & 0x3fL]
              ^ SP1[(work >> 24) & 0x3fL];
        work  = right ^ *keys++;
        leftt ^= SP8[ work        & 0x3fL]
              ^  SP6[(work >>  8) & 0x3fL]
              ^  SP4[(work >> 16) & 0x3fL]
              ^  SP2[(work >> 24) & 0x3fL];

        work = RORc(leftt, 4) ^ *keys++;
        right ^= SP7[ work        & 0x3fL]
              ^  SP5[(work >>  8) & 0x3fL]
              ^  SP3[(work >> 16) & 0x3fL]
              ^  SP1[(work >> 24) & 0x3fL];
        work  = leftt ^ *keys++;
        right ^= SP8[ work        & 0x3fL]
              ^  SP6[(work >>  8) & 0x3fL]
              ^  SP4[(work >> 16) & 0x3fL]
              ^  SP2[(work >> 24) & 0x3fL];
    }

    tmp = des_fp[0][BYTE (leftt, 0)] ^
          des_fp[1][BYTE (leftt, 1)] ^
          des_fp[2][BYTE (leftt, 2)] ^
          des_fp[3][BYTE (leftt, 3)] ^
          des_fp[4][BYTE (right, 0)] ^
          des_fp[5][BYTE (right, 1)] ^
          des_fp[6][BYTE (right, 2)] ^
          des_fp[7][BYTE (right, 3)];

    leftt = uint32_t (tmp >> 32);
    right = uint32_t (tmp & 0xFFFFFFFFUL);

    block[0] = right;
    block[1] = leftt;
}


//----------------------------------------------------------------------------
// Schedule a new key. If rounds is zero, the default is used.
//----------------------------------------------------------------------------

bool ts::DES::setKeyImpl(const void* key, size_t key_length, size_t rounds)
{
    if (key_length != KEY_SIZE || (rounds != 0 && rounds != ROUNDS)) {
        return false;
    }

    deskey (reinterpret_cast<const uint8_t*> (key), EN0, _ek);
    deskey (reinterpret_cast<const uint8_t*> (key), DE1, _dk);

    return true;
}


//----------------------------------------------------------------------------
// Encryption in ECB mode.
//----------------------------------------------------------------------------

bool ts::DES::encryptImpl(const void* plain, size_t plain_length, void* cipher, size_t cipher_maxsize, size_t* cipher_length)
{
    if (plain_length != BLOCK_SIZE || cipher_maxsize < BLOCK_SIZE) {
        return false;
    }

    uint32_t work[2];
    work[0] = GetUInt32 (plain);
    work[1] = GetUInt32 (reinterpret_cast<const uint8_t*> (plain) + 4);

    desfunc (work, _ek);

    PutUInt32 (cipher, work[0]);
    PutUInt32 (reinterpret_cast<uint8_t*> (cipher) + 4, work[1]);

    if (cipher_length != nullptr) {
        *cipher_length = BLOCK_SIZE;
    }

    return true;
}


//----------------------------------------------------------------------------
// Decryption in ECB mode.
//----------------------------------------------------------------------------

bool ts::DES::decryptImpl(const void* cipher, size_t cipher_length, void* plain, size_t plain_maxsize, size_t* plain_length)
{
    if (cipher_length != BLOCK_SIZE || plain_maxsize < BLOCK_SIZE) {
        return false;
    }

    uint32_t work[2];
    work[0] = GetUInt32 (cipher);
    work[1] = GetUInt32 (reinterpret_cast<const uint8_t*> (cipher) + 4);

    desfunc (work, _dk);

    PutUInt32 (plain, work[0]);
    PutUInt32 (reinterpret_cast<uint8_t*> (plain) + 4, work[1]);

    if (plain_length != nullptr) {
        *plain_length = BLOCK_SIZE;
    }

    return true;
}


//----------------------------------------------------------------------------
// Constructor
//----------------------------------------------------------------------------

ts::DES::DES() :
    _ek(),
    _dk()
{
}


//----------------------------------------------------------------------------
// Implementation of BlockCipher interface:
//----------------------------------------------------------------------------

ts::UString ts::DES::name() const
{
    return u"DES";
}
size_t ts::DES::blockSize() const
{
    return BLOCK_SIZE;
}
size_t ts::DES::minKeySize() const
{
    return KEY_SIZE;
}
size_t ts::DES::maxKeySize() const
{
    return KEY_SIZE;
}
bool ts::DES::isValidKeySize (size_t size) const
{
    return size == KEY_SIZE;
}
size_t ts::DES::minRounds() const
{
    return ROUNDS;
}
size_t ts::DES::maxRounds() const
{
    return ROUNDS;
}
size_t ts::DES::defaultRounds() const
{
    return ROUNDS;
}
